Vue notes (instructions/components/life cycle/routing)

Vue creates elementUI project

vue create my-app
cd my-app
vue add element-plus

Two major features of Vue

  1. Data Driven View

    1. Data changes will drive the view to automatically update
    2. Benefits: Programmers only need to maintain the data, then the page structure will be automatically rendered by vue
  2. two-way data binding

    1. In web pages, the form form is responsible for collecting data, and Ajax is responsible for submitting data
    2. The change of js data will be automatically rendered on the page
    3. When the data of the financial season in the form on the page changes, it will be automatically obtained by vue and updated to the js data

    Note: The underlying principle of data-driven view and data two-way data binding is MVVM (Model data source, View view, ViewModle is an instance of Vue)

Vue directives

1. Content rendering instruction: used to assist developers in rendering the text content of DOM elements

  • v-text (hardly used)
    • Disadvantage: it will overwrite the original content inside the element
  • { {}} Interpolation expression (Mustache) (used more)
  • v-html: can render tagged strings into real HTML content

2. Attribute binding instructions (note: interpolation expressions can only be used in the content node of the element, not in the attribute node of the element!)

  • v-bind can dynamically bind values ​​for the attributes of elements, abbreviated as colons ( : )
    • During binding with the v-bind attribute, if the binding content needs to be spliced ​​dynamically, the string should be wrapped in single quotes

3. Event binding

  1. v-on: The abbreviation is @
  2. The syntax format is:
<button @click="add"></button>

methods: {
	add() {
			this.count += 1
	}
}
  1. Application scenario of event: If the default event object e is overridden, you can manually pass an event Application scenario: If the default event object e is overwritten, you can manually pass oneApplication scenarios of e v e n t:If the default event object e is overridden , _You can manually pass an event
<button @click="add(3, $evnet)"></button>

methods: {
	add(n, e) {
			this.count += 1
}
}
  1. event modifier

    • .prevent prevents the default event
    <a @click.prevent="xxx">url</a>
    
    • .stop prevents bubbling events
    <button @click.stop="xxx">button</button>
    
    • .capture triggers the current time processing function in capture mode
    • once The binding time is only triggered once
    • self triggers the event handler only when event.target is the current element itself

4. The v-model directive

  1. input input box
    1. type=“radio”
    2. type=“checkbox”
    3. type=“xxxx”
  2. textarea
  3. select
  • In order to facilitate the processing of user input, vue provides 3 modifiers for the v-model directive
Modifier effect example
.number Automatically convert user input values ​​to numeric types

5. Conditional rendering instructions

  • Conditional rendering instructions are used to assist developers to control the display and hiding of DOM as needed .
  1. v-if: Dynamically create or remove elements each time to realize the display and hiding of elements ( commonly used in actual development )
    • If some elements do not need to be displayed by default when you first enter the page, and this element may not need to be displayed later, at this time v-if performance is better
    • Companion instruction for v-if: v-else-if / v-else
  2. v-show: Dynamically add or remove the display:none style for the element to realize the display and hiding of the element
    • If you want to switch the display status of elements frequently, the performance of v-show will be better

6. Loop rendering instructions

  1. Add v-for to which element to loop
  2. Official suggestion: As long as the v-for command is used, a :key attribute must be bound, and try to use id as the value of the key
  3. The official value type of the key is required to be: string or number type
  4. The value of key cannot be repeated, otherwise the terminal will report an error
<div id="app">
    <table class="table table-bordered table-hover">
        <thead>
        <th>索引</th>
        <th>Id</th>
        <th>姓名</th>
        </thead>
        <tbody>
        <tr v-for="(item, index) in list" :key="item.id">
            <td>{
   
   { index }}</td>
            <td>{
   
   { item.id }}</td>
            <td>{
   
   { item.name }}</td>
        </tr>
        </tbody>
    </table>
</div>

listener (watch)

  1. listener in method format
    • Disadvantage 1: It can no longer be triggered automatically when entering the page
    • Disadvantage 2: If the listener is an object, if the properties in the object change, the listener will not be triggered
  2. Object format listener
    • Benefit 1: The listener can be triggered automatically through the immediate option
    • Benefit 2: You can use the deep option to let the listener deeply monitor the changes of each property in the object

Computed property (computed)

  • features
    • When defining, it must be defined as a method
    • When using computed properties, it can be used as ordinary properties
  • benefit
    • Implemented code reuse
    • As long as the data source dependent in the computed property changes, the computed property will automatically re-evaluate!

axios

axios is a library focused on network requests

1. Initiate a get request

axios({
    
    
        // 请求方式
        method: 'GET',
        // 请求地址
        url: 'http://www.liulongbin.top:3006/api/getbooks',
        // url 中的查询参数(一般 get 请求)
        params: {
    
    
            id: 1
        },
        // 请求体参数(一般 post 请求)
        data: {
    
    }
    }).then(function (result) {
    
    
        console.log(result);
    });
// Get 请求简化
document.querySelector('#btnGet').addEventListener('click', async () => {
    
    
    // 解构赋值的时候, 使用 : 进行重命名
    // 1. 调用 axios 之后, 使用 async/await 进行简化
    // 2. 使用解构赋值, 从 axios 封装的大对象中, 把 data 属性解构出来
    // 3. 把解构出来的 data 属性, 使用冒号进行重命名, 一般都重命名为 { data: res}
    const {
    
    data: res} = await axios({
    
    
        method: 'GET',
        url: 'http://www.liulongbin.top:3006/api/getbooks'

    });
    console.log(res.data);
});
// Get 请求模板
document.querySelector('#btnGet').addEventListener('click', async () => {
    
    
    const {
    
    data: res} = await axios.get(
        // 请求 url
        '',
        // 请求参数
        {
    
    
            params: {
    
    }
        }
    );
    console.log(res.data);
});

2. Initiate a post request

document.querySelector('#btnPost').addEventListener('click',
    async () => {
    
    
        // 如果调用某个方法的返回值是 Promise 实例, 则可以前面添加 await
        // await 只能用在被 async 修饰的方法中
        // 1. 调用 axios 方法得到的返回值是 Promise 对象
        const {
    
    data} = await axios({
    
    
            // 请求方式
            method: 'POST',
            // 请求地址
            url: 'http://www.liulongbin.top:3006/api/post',
            // url 中的查询参数(一般 get 请求)
            params: {
    
    },
            // 请求体参数(一般 post 请求)
            data: {
    
    
                name: 'zs',
                age: 20
            }
        });
        console.log(data);
    });
// Post 请求模板
document.querySelector('#btnPost').addEventListener('click', async () => {
    
    
    // axios.post('url',{/*Post 请求体数据*/})
    const {
    
    data: res} = await axios.post(
        // 请求 url
        '',
        // 请求体
        {
    
    });
    console.log(res);
});

3. Using axios in Vue

methods: {
    
    
  async btnGetBooks() {
    
    
    const {
    
     data: res } = await axios.get('/api/getbooks')
    console.log(res)
  }
}

Use of vue-cli

  1. Run the following command in the terminal to create a project with the specified name
vue create 项目的名称
  1. The composition of the src directory in the vue project
assets 文件夹: 存放项目中用到的静态资源文件, 例如: css 样式表, 图片资源
components 文件夹: 程序员封装的, 可复用的组件, 都要方法哦 components 目录下
main.js 是项目的入口文件.整个项目的运行, 都要先执行 main.js
App.vue 是项目的根组件

Three steps to use components

  1. Use the import syntax to import the required components
import Left from '@/components/Left.vue'
  1. Register components using the components node
export default {
    
    
	components: {
    
    
			Left
	}
}
  1. Use the just registered component as a tag
<div class="box">
		<Left></Left>
</div>

Register global components

In the main.js entry file of the vue project, the global component can be registered through the Vue.component() method

import Count from '@/components/Count.vue'
Vue.component('MyCount', Count)
// 参数 1:字符串格式, 表示组件的"注册名称"
// 参数 2:需要被全局注册的那个组件

Component props

props is a custom attribute of a component. When encapsulating common components, using props reasonably can greatly improve the reusability of components!

  • props is read-only: if you want to modify the value of props, you can dump the value of props into data
export default {
    
    
  props: ['自定义属性A','自定义属性B','其他自定义属性...']
}
// props 设置 default 值, 设置 type 值类型, 设置 required 必填项
export default {
    
    
  props: {
    
    
    init: {
    
    
      default: 0,
      type: Number,
      required: true
    }
  },
}

scoped and deep

  • scoped scope style
  • deep: Add /deep/ before the style to modify the style of the child component in the parent component (commonly used to modify the default style of third-party components)

Component life cycle

Life Cycle (Life Cycle) refers to the entire stage of a component from creation -> operation -> destruction , emphasizing a time period

  1. Component Creation Phase
    • new Vue() -> beforeCreate -> created -> breforeMount -> mounted
  2. component runtime
    • beforeUpdate -> updated
  3. Component destruction phase
    • beforeDestroy->destroyed
stage illustrate features Is it commonly used
beforeCreate The first life cycle function of the creation phase uncommonly used
created Initiate an Ajax request (call methods in methods, request server data, and transfer the requested data to data for template rendering) Initialize props/data/methods very commonly used
beforeMount rarely used
mounted If you want to operate the DOM, you must be in the mounted stage at the earliest Initialize the DOM commonly used
beforeUpdate generally
updated When the data changes, in order to be able to operate the latest DOM structure, the code must be written into the updated lifecycle function commonly used
beforeDestroy generally
destroyed generally
Vue life cycle diagram

Data Sharing Between Components

  1. Parent components share data with child components

    • You need to use custom properties ( props ) in the child component, and use v-bind to pass the value in the parent component
  2. Child components share data with parent components

    • Child components share data with parent components using custom events
// 子组件 
methods: {
    
    
    add() {
    
    
      this.count += 1;
      this.$emit('numChange', this.count);
    }
  }
// 父组件
<h1>{
    
    {
    
     countFromSon }}</h1>
<Right @numChange="getNewCount"></Right>

data() {
    
    
    return {
    
    
      // 定义数据项来接收子组件传递过来的值
      countFromSon: 0
    };
  },
  methods: {
    
    
    // 获取子组件传递过来的数据
    getNewCount(val) {
    
    
      console.log('numChange 事件被触发了!', val);
      this.countFromSon = val;
    }
  }
  1. Data sharing between sibling components
    • In vue 2.x, the data sharing scheme between sibling components is EventBus
// eventBus.js
import Vue from 'vue'

export default new Vue()
// 子组件
<template>
  <div class="Count">
    <button type="button" @click="sub">-</button>
    <span class="number-box">{
   
   { num }}</span>
    <button type="button" @click="add">+</button>
  </div>
</template>

<script>
import bus from '@/components/eventBus.js';

export default {
  name: "Counter",
  props: {
    id: {
      type: Number,
      required: true
    },
    num: {
      type: Number,
      default: 1
    }
  },
  methods: {
    add() {
      bus.$emit('share',
          {
            id: this.id,
            value: this.num + 1
          });
    },

    sub() {
      bus.$emit('share',
          {
            id: this.id,
            value: this.num - 1
          });
    }
  }
};
</script>
// 兄弟组件
import bus from '@/components/eventBus.js';

  created() {
    bus.$on('share', val => {
      this.list.some(item => {
        if (item.id === val.id) {
          item.goods_count = val.value;
          return true
        }
      });
    });
  }

ref reference

  • Used to assist developers to obtain references to DOM elements or components without relying on jQuery
  • Each vue component instance contains a ** refs object∗ ∗, which stores the reference of the corresponding DOM element or component. By default, the refs object of ∗ ∗ component** stores the reference of the corresponding DOM element or component. By default, **component'sr e f s object,It stores the reference of the corresponding DOM element or component . By default , _ _ _The component 's refs point to an empty object**
  • You can use ref to share data between components
<h1 ref="myh1">App 根组件</h1>
console.log(this.$refs.myh1);

this.$nextTick(cb) method

  • The $nextTick(cb) method of the component will postpone the execution of the cb callback until the next DOM update cycle. The popular understanding is: after the component DOM update is completed, then execute the cb callback function. This ensures that the cb callback function can operate to the latest DOM element
this.$nextTick(() => {
    
    
  this.$refs.iptRef.focus();
})

Dynamic Component Rendering

  • Vue provides a built-in component, which is specially used to realize the rendering of dynamic components
  • Dynamic components will be re-destroyed and re-created every time they are switched -- keep-alive solution
<template>
    <div class="app-container">
        <h1>App 根组件</h1>
        <hr/>

        <button @click="comName='Left'">展示 Left</button>
        <button @click="comName='Right'">展示 Right</button>
        <div class="box">
            <!-- 渲染 Left 组件和 Right 组件 -->
            <!-- 1. component 标签是vue内置的, 作用: 组件的占位符-->
            <!-- 2. is 属性的值, 表示要渲染的组件的名字-->
            <!-- 3 is 属性的值, 应该是组件要再components节点下的注册名称-->
            <!-- keep-alive 可以把内部的组件进行缓存, 而不是销毁组件-->
            <keep-alive include="Left, Right">
                <component :is="comName"></component>
            </keep-alive>
        </div>
    </div>
</template>

data() {
        return {
            // comName: 表示要展示的组件的名字
            comName: 'Left'
        };
    }
  • The life cycle function corresponding to keep-alive

    • When the component is cached , the component's deactivated lifecycle function is automatically triggered
    • When the component is activated , the activated lifecycle function of the component is automatically triggered
  • The include attribute of keep-alive: components with matching names will be cached, and multiple components are separated by English commas

  • The exclude attribute of keep-alive: Exclude the cache of the specified name component (choose one of include and exclude)

slot

  • Slot (slot) is the ability provided by vue to the wrapper of the component . Allows developers to define undefined parts that are expected to be specified by users as slots when packaging components .
    • If you want to fill the content into the slot with the specified name, you need to use v-slot: this command
    • v-slot: followed by the name of the slot
    • v-slot: Directives cannot be used directly on elements, they must be used on the template tab ( or directly on components! )
    • template This tag, it is a virtual tag, it only plays the role of wrapping, but it will not be rendered as any substantial html element
  • The shorthand for v-slot is #
// 子组件
<!-- vue 官方规定, 每一个slot插槽, 都要有一个 name 名称, 省略默认为 default-->
<slot name="default">这是 default 插槽的默认内容</slot>

// 父组件
<Left>
    <template #default>
		<p>这是在Left组件的内容区域, 声明的p标签</p>
    </template>
</Left>

Scoped slots

  • When encapsulating a component, provide the reserved slot with the value corresponding to the attribute. This usage is called "scope slot"
// 子组件
<slot name="content" msg="hello vue" :user="userinfo"></slot>

// 父组件:用法 1
<template #content="obj">
  <div>
    <p>{
   
   { obj.msg }}</p>
    <p>{
   
   { obj.user}}</p>
  </div>
</template>

// 父组件:用法 2
<template #content="{msg, user}">
  <div>
    <p>{
   
   { msg }}</p>
    <p>{
   
   { user }}</p>
  </div>
</template>

custom directive

1. Private custom directive

<h1 v-color="color">App 根组件</h1>
<h3 v-color="'red'">测试</h3>

data() {
    
    
        return {
    
    
            color: 'blue'
        };
    },
// 私有自定义指令的节点
directives: {
    
    
        // 定义名为 color 的自定义指令,指向一个配置对象
        color: {
    
    
            // 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
            // 形参中的 el 表示当前指令所绑定的那个 DOM 对象
            bind(el, binding) {
    
    
                console.log('触发了 v-color 的 bind 函数');
                el.style.color = binding.value;
            },
            // 每次 DOM 更新时被调用
            update(el, binding) {
    
    
                console.log('触发了 v-color 的 update 函数');
                el.style.color = binding.value;
            }
        }
}
// 如果 bind 和 update 事件一样,可以简写
directives: {
    
    
    color(el, binding) {
    
    
        el.style.color = binding.value;
    }
}

2. Global custom directives

// 全局自定义指令
Vue.directive('color', function (el, binding) {
    
    
    el.style.color = binding.value;
});

Mount axios on the Vue prototype

// main.js
import axios from 'axios'

// 全局配置 axios 的请求根路径
axios.defaults.baseURL = 'http://localhost:8080'
// 把 axios 挂载到 Vue.prototype 上,供每个 .vue 组件的实例直接使用
Vue.prototype.$http = axios

// 今后,在每个 .vue 组件中要发起请求,直接调用 this.$http.xxx
// 但是,把 axios 挂载到 Vue 原型上,有一个缺点:不利于 API 接口的复用!!!

routing

  • Routing (router) is the corresponding relationship
  • Front-end routing : the correspondence between Hash addresses and components
  • How Frontend Routing Works
    1. The user clicks a route link on the page
    2. Caused the Hash value in the URL address bar to change
    3. The front-end routing has monitored the change of the Hash address
    4. The front-end routing renders the component corresponding to the current Hash address into the browser
  • Vue-router installation and configuration steps
    1. Install the vue-router package
    2. Create routing module
    3. Import and mount the routing module
    4. Declare routing links and placeholders
// src/router/index.js 就是当前项目的路由模块
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '@/components/Home';
import Movie from '@/components/Movie';
import About from '@/components/About';
import Tab1 from '@/components/tabs/Tab1';
import Tab2 from '@/components/tabs/Tab2';

Vue.use(VueRouter);

// 创建路由的实例对象
const router = new VueRouter({
    
    
    // routes 是一个数组,作用:定义 hash 地址与组件之间的对应关系
    routes: [
        // 重定向的路由规则
        {
    
    path: '/', redirect: '/home'},

        // 路由规则
        {
    
    path: '/home', component: Home},
        {
    
    path: '/movie/:id', component: Movie, props: true},
        {
    
    // about 页面的路由规则(父级路由规则)
            path: '/about',
            component: About,
            redirect: '/about/tab1',
            children: [
                // 子路由规则
                // 默认子路由:如果 children 数组中,某个路由规则的 path 值为空,字符串,则这条路由规则,叫做默认子路由
                {
    
    path: 'tab1', component: Tab1},
                {
    
    path: 'tab2', component: Tab2}
            ]
        }
    ]
});

export default router;
<!-- 当安装和配置了 vue-router 后,就可以用 router-link 来替代普通的 a 链接了-->
<router-link to="/home">首页</router-link>

<!--只要在项目中安装和配置了 vue-router,就可以使用 router-view 这个组件了-->
<!--作用:占位符-->
<router-view></router-view>
  • Routing redirection: When a user accesses address A, the user is forced to jump to address C to display a specific component page. By specifying a new routing address through the redirect attribute of routing rules, it is very convenient to set routing redirection.

  • Dynamic routing : Define the variable part of the Hash address as a parameter item, thereby improving the reusability of routing rules. Use the English colon (:) in vue-router to define the parameter items of the route.

  • props: true : enable props to pass parameters for routing rules, so as to easily get the value of dynamic parameters

<!-- 当安装和配置了 vue-router 后,就可以用 router-link 来替代普通的 a 链接了-->
<router-link to="/home">首页</router-link>
<!-- 注意:在 hash 地址中,/后面的参数项,叫做"路径参数"-->
<!-- 在路由参数对象中,需要使用 this.$route.params 来访问路径参数-->
<!-- 注意2:在 hash 地址中,?后面的参数项,叫做"查询参数"-->
<!-- 在路由参数对象中,需要使用 this.$route.query 来访问查询参数-->
<!-- 注意3:在 this.$route中,path 只是路径部分,fullPath 是完整的地址-->
<!--例如:-->
<!--fullPath:/movie/2?name=zs&age=20-->
<!--/movie/2 是 path 的值-->
<router-link to="/movie/1">电影1</router-link>
<router-link to="/movie/2?name=zs&age=20">电影2</router-link>
<router-link to="/movie/3">电影3</router-link>
<router-link to="/about">关于</router-link>

Programmatic Navigation API in Vue-router

  1. this.$router.push('hash address')
    • Jump to the specified hash address and add a history record
  2. this.$router.replace('hash address')
    • Jump to the specified hash address and replace the current history
  3. this.$router.go(number n) (forward and backward)
  4. Simplified usage of $router.go
    • $router.back()
    • $router.forward()

route guard

  1. Global Front Guard
    • Every time a routing navigation jump occurs , the global pre-guard will be triggered . Therefore, in the global front guard, programmers can control the access rights of each route.
router.beforeEach((to, from, next) => {
    
    
    // to 是将要访问的路由信息对象
    // from 是将要离开的路由的信息对象
    // next 是一个函数,调用 next()表示放行,允许这次路由导航
    // 分析:
    // 1. 要拿到用户将要访问的 hash 地址
    // 2. 判断 hash 地址是否等于 /main
    // 2.1 如果等于/main,证明需要登录之后,才能访问成功
    // 2.2 如果不等于 /main,则不需要登录,直接放行 next()
    // 3. 如果访问的地址是 /main,则需要读取 localStorage 中的 token 值
    // 3.1 如果有 token,则放行
    // 3.2 如果没有 token,则强制跳转到/login 登录界面
    if (to.path === '/main') {
    
    
        const token = localStorage.getItem('token');
        if (token) {
    
    
            next();
        } else {
    
    
            next('/login');
        }
    } else {
    
    
        next();
    }
});

Guess you like

Origin blog.csdn.net/lzykevin/article/details/122743171