The directives, lifecycle hooks and router APIs below primarily target Vue 2 / Vue Router 3; Vue 3 differences appear at the end.
basic knowledge
Template
The template of vue.js uses template syntax based on html, and the data binding in the template uses "Mustache" syntax (double brackets).Double brackets will parse the data into ordinary text instead of html code. If you want to output real html, you need to use v-html. The double bracket syntax cannot be used on Html Attribute. In this case, you need to use the v-bind instruction.
<div v-bind:id="dynamicId"></div>If the value of dynamicId is null, undefined or false, the disabled attribute will not even be included in the rendered <div> element.
Full expression support is provided in templates, but each binding can only contain a single expression, so the following will not take effect
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}TIP
Template expressions are placed in the sandbox and can only access a whitelist of global variables. Do not try to access user-defined global variables in the template.
instructions
Directives are special attributes prefixed with v-.The responsibility of the directive is to reactively apply its associated effects to the DOM when the value of the expression changes.
Common commands
- v-if conditional rendering instruction, representing existence and destruction
- v-bind binding instruction, used to bind attributes (abbreviation:)
- v-on event binding instruction (abbreviated @)
- v-for loop command
- v-text content is displayed as text equivalent to {
- v-html content is inserted as normal HTML
- v-once only renders once
Common command abbreviations
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a><!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>Custom instructions
In Vue 2, custom directives are created by using the hooks listed below, which are all optional
- bind - Occurs after the directive is bound to an element.Only happens once.
- inserted - Occurs after the element is inserted into the parent DOM.
- update - This hook is called when an element is updated, but child elements have not yet been updated.
- componentUpdated - This hook is called once the component and children have been updated.
- unbind - This hook is called once the directive has been removed.Also only called once.
<p v-highlight="yellow">高亮显示此文本亮黄色</p>Vue.directive('highlight', {
bind(el, binding, vnode) {
el.style.background = binding.value
}
})computed and watch
computed:🎉:
- The results of computed properties are cached and will not be recalculated unless the dependent reactive property changes.
- Asynchronous is not supported. It is invalid when there are asynchronous operations in computed and cannot monitor data changes.
- If an attribute is calculated from other attributes, this attribute depends on other attributes, it is a many-to-one or one-to-one, generally use computed
When the expression logic in the template is complex, computed properties should be used.
Why does it need to be cached: Because it is a relatively expensive calculated attribute A, which requires traversing a huge array to do a lot of calculations, and then we have other attributes that depend on A.If it is not cached, we will inevitably execute A's getter multiple times.
watch:🎉:
Caching is not supported and data changes will directly trigger corresponding operations.
watch supports asynchronous
When an attribute changes, corresponding operations need to be performed; one-to-many
The listening data must be data declared in data or in props passed by the parent component. When the data changes, other operations are triggered. The function has two parameters:
Add immediate to watch to trigger immediate execution immediate: component loading immediately triggers callback function execution.
deep: Deep monitoring is used for detecting changes in the internal values of objects and complex types of data, such as changes in object content in an array. Note that this is not required to monitor changes in the array.Note: deep cannot monitor array changes and object additions. Please refer to vue array mutation. It can only be monitored if it is triggered in a responsive manner.v-for loop
The v-for instruction loop needs to carry the key, because when the DOM does a diff comparison, it will make a series of comparisons between the start and the end. If it hits, the key of the new node will be compared with the key of the old node. If it does not match, a new element will be used. If the key is matched and the tag of the old node is the same as the tag of the new node, it will be considered to be an old node.Reduce the number of comparisons.
life cycle
beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、activated、deactivated、beforeDestroy、destroyed、errorCaptured
Requests may start in created; use mounted for work requiring mounted DOM. Asynchronous rendering does not replay created; investigate instance recreation, SSR or business triggers for duplicates.
life cycle function
In a parent-child component, at a certain stage, the parent component life cycle will be executed first, and then the child component life cycle will be executed. The child component completes the life cycle first and then the parent component completes the life cycle. For example:
parentbeforeCreate parentcreated
child beforeCreate child created
beforeCreate is called before data detection event configuration
create is called after data monitoring and events (watch, event) take effect
beforeMount is executed after the related render is called for the first time.
mounted is called after the instance is mounted.
beforeUpdate is called when the data is updated. Before the virtual DOM is patched, it is suitable for updating and accessing the existing DOM, such as removing the added event listener.
update The data has been updated to avoid changing status during this period.update does not guarantee the update of all sub-components. If you want to finish drawing the entire view, you can use vm.$nextTick in updated to execute it.
activated is called when a component cached by keep-alive is activated
deactivate is called when a component cached by keep-alive is deactivated.
beforeDestroy is called before the instance is destroyed, at which point the instance is still fully available.Unbind custom events event.$off, clear timers, unbind custom DOM events, such as window.scroll, etc.
After the destroyed instance is destroyed, the corresponding vue command is called to unbind, the event listener is removed, and the sub-instance is also destroyed.
errorCaptured Called when capturing an error from a descendant component.This hook will receive three parameters: the error object, the component instance where the error occurred, and the error source information string.This hook can return false to prevent the error from continuing to propagate upward.
Component communication
- Data passed from parent component A to child component B can be passed down to the child component through props.Props should not be changed inside a child component.If you do this, Vue will issue a warning in the browser's console.
Tips
Note that in JavaScript objects and arrays are passed in by reference, so for an array or object type prop, changing the object or array itself in the child component will affect the state of the parent component.
- Child components pass values to parent components through events.The child component sends data to the event carried when calling the parent component through $emit.
- Bidirectional data binding of a prop through the sync modifier is equivalent to the abbreviation of No. 1 and No. 2.
// 子组件
this.$emit('update:title', newTitle)
// 父组件
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
// 简写
<text-document v-bind:title.sync="doc.title"></text-document>
4. 自定义事件
5. slot 作用域插槽
6. vuex
//修改方式: 1)可以直接使用 this.$store.state.变量 = xxx;
2)this.$store.dispatch(actionType, payload)
或者:this.$store.commit(commitType, payload)Custom component v-model
A component v-model will make use of a prop named value and an event named input by default, but input controls such as radio buttons, check boxes, etc. may use the value attribute for different purposes.The model option can be used to avoid such conflicts:
// 子组件
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
// 父组件
<base-checkbox v-model="lovingVue"></base-checkbox>nextTick
Vue renders asynchronously, and the dom will not be rendered after the data is modified.$nextTick will be triggered after the dom is rendered.To get the latest dom node.
Vue will give priority to using native Promise.then and MutationObserver according to the current browser environment. If neither is supported, setTimeout will be used instead. The purpose is to delay the function until the DOM is updated before using it.
Dynamic components & asynchronous components
- dynamic components
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<!-- 动态组件 -->
<component v-bind:is="currentTabComponent"></component>
</keep-alive>- Asynchronous components In large applications, we may need to split the application into smaller chunks of code and load a module from the server only when needed.To simplify, Vue allows you to define your component as a factory function, which will parse your component definition asynchronously.Vue will only trigger the factory function when the component needs to be rendered, and cache the results for future re-rendering.
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包,这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
Vue.component(
'async-webpack-example',
// 这个动态导入会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
new Vue({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})Tips
Note that if you want to use the above syntax in Vue Router's routing component, you must use Vue Router 2.4.0+ version.
keep-alive
- Cache component
- Frequent switching does not require repeated rendering
- The difference from v-show is that v-show is implemented by CSS style, and keep-alive is the control of the vue layer. Simple ones can be v-show, and complex ones like tab switching can be kept-alive.
Props:
- include - string or regular expression.Only components with matching names will be cached.
- exclude - string or regular expression.Any component with a matching name will not be cached.
- max - number.The maximum number of component instances that can be cached.
The include and exclude props allow components to be cached conditionally.Both can be represented as a comma-separated string, a regular expression, or an array:
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b"> // 这里的a,b是注册的component名
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>Life cycle when there is keep-alive:
When loading: parent-beforeCreate ==> parent-created ==> parent-beforeMount ==> child-beforeCreate ==> child-created ==> child-beforeMount ==> child-Mounted ==> child-actived ==> parent-mounted
When destroyed: parent-beforeDestroy==> child-deactived ==> child-beforeDestroy ==> child-Destroyed ==> parent-Destroyed
mixin
Extract the same logic of multiple components and put them together. The referenced hooks are called in the order they are passed in, and will be called before calling the component hook.
Question:
- The source of the variable is unclear
- Multiple variables may conflict
- There may be a many-to-many relationship with components, and the complexity is high.
vue-router
There are three modes of vue-router: "hash" | "history" | "abstract"
Default values are: "hash" (browser environment) | "abstract" (Node.js environment)
- hash: Use URL hash value for routing.Supports all browsers, including browsers that don't support the HTML5 History API.
- history: relies on HTML5 History API and server configuration.See HTML5 History mode.
- abstract: Supports all JavaScript runtime environments, such as Node.js server-side.If no browser API is found, the router will automatically force into this mode.
Common parameters for creating routes
- path path
- name named route
- components named view components
- meta
- alias
- children nested routing
- redirect redirect
- props // 2.6.0+
- caseSensitive?: boolean, // Are the matching rules case-sensitive?(Default: false)
- pathToRegexpOptions?: Object // Compile regular options
router instance methods
Global hook function
- router.beforeEach global front guard, called when routing switching starts, must call
next.When a navigation is triggered, global front guards are called in the order they were created.Guards are parsed and executed asynchronously. At this time, the navigation is waiting until all guards are resolved.
next method
next(): Proceed to the next hook in the pipeline.If all hooks are executed, the navigation status is confirmed.
next(false): Interrupt current navigation.If the browser's URL changes (perhaps manually by the user or by the browser's back button), the URL address will be reset to the address corresponding to the from route.
next('/') or next({ path: '/' }): Jump to a different address.The current navigation is interrupted and a new navigation is started.You can pass an arbitrary location object to next, and options such as replace: true, name: 'home', and any options used in router-link's to prop or router.push are allowed to be set.
next(error): (2.4.0+) If the parameter passed to next is an Error instance, the navigation will be terminated and the error will be passed to the callback registered by router.onError().
- router.beforeResolve global resolution guard, must call
next
In 2.5.0+ you can register a global guard with router.beforeResolve.This is similar to router.beforeEach, except that before the navigation is confirmed, 同时在所有组件内守卫和异步路由组件被解析之后 , the parsing guard is called.
- router.afterEach runs after navigation is confirmed; it receives no next argument and does not change the navigation result
- beforeEnter is a per-route configuration guard with the same arguments as global before guards.
- Guards within components
- beforeRouteEnter
- beforeRouteUpdate (new in 2.2)
- beforeRouteLeave
jsconst Foo = { template: `...`, beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 // 你可以通过传一个回调给 next来访问组件实例。 next(); }, beforeRouteUpdate(to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` next(); }, beforeRouteLeave(to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` next(); } } - Programmatic navigation
- router.push
- router.replace
- router.go
- router.back
local to single route
- beforeEnter
Component hook routing
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
🎉 Use of global routing
router.beforeEach((to, from, next) =>{
// to 表示即将进入的目标对象
// from 当前要离开的路由对象
// 调用 next() 放行;每条执行路径都应且只能调用一次
next();
})Complete navigation analysis process
Main guard order: beforeRouteLeave => beforeEach => beforeRouteUpdate => beforeEnter => beforeRouteEnter => beforeResolve => afterEach (only guards applicable to this navigation run; see the complete flow below)
TIP
beforeEnter runs when entering the corresponding route record, including a root route; changing only params, query, or hash on the same route does not trigger it again.
If a component route is switched to another group, the beforeRouteLeave in the component will be triggered first and then the beforeEach global route guard will be triggered.
- Navigation is triggered.
- Call the beforeRouteLeave guard in the deactivated component.
- Call the global beforeEach guard.
- Call the beforeRouteUpdate guard in reused components (2.2+).
- Call beforeEnter in routing configuration.
- Resolve asynchronous routing components.
- Call beforeRouteEnter in the activated component.
- Call the global beforeResolve guard (2.5+).
- Navigation is confirmed.
- Call the global afterEach hook.
- Trigger DOM update.
- Call the callback function passed to next in the beforeRouteEnter guard, and the created component instance will be passed in as a parameter of the callback function.
Differences of vue3
- Removed filters
- I used prototype in the past, but now I don’t recommend using it.
- ref cannot be used directly
- Added setup
- Add combined API
- life cycle
- Different ways of defining props
Parent-child component passing parameters
Vue 3 uses emit and update: to implement data transfer between parent and child components.
update: used to bind the data of the child component through v-model in the parent component, and trigger an update:modelValue event in the child component to update the data.For example, in a child component:
<!-- 子组件 -->
<template>
<input :value="modelValue" @input="updateValue">
</template>
<script>
export default {
props: ['modelValue'],
methods: {
updateValue(event) {
this.$emit('update:modelValue', event.target.value);
}
}
}
</script>
<!-- 父组件 -->
<template>
<child-component v-model="data"></child-component>
</template>
<script>
export default {
data() {
return {
data: 'initial data'
}
}
}
</script>Define props
<!-- 子组件声明了的 props ,若父组件未传,则该值为 undefined -->
<script lang='ts' setup>
const props = defineProps({
child: {
type:String, // 参数类型
default: 1, //默认值
required: true, //是否必传
validator: value => {
return value >= 0 // 除了验证是否符合type的类型,此处再判断该值结果是否符合验证
}
},
sda: String, //undefined
strData: String,
arrFor: Array
})
</script>
<!-- 类型声明方式 -->
<script lang='ts' setup>
const props = defineProps<{
either: '必传且限定'|'其中一个'|'值', // 利用TS:限定父组件传 either 的值
child?: string|number,
strData?: string,
arrFor: any[]
}>();
console.log(props);
</script>
<!-- 类型声明添加默认值 :默认值为引用类型的,需要包装一个函数 return 出去。-->
<script lang='ts' setup>
interface Props {
either: '必传且限定'|'其中一个'|'值', // 利用TS:限定父组件传 either 的值
child: string|number,
sda?: string, // 未设置默认值,为 undefined
strData: string,
msg?: string
labels?: string[],
obj?:{a:number}
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two'],
obj: () => { return {a:2} }
})
</script>Others
- After moving from
el-dialogin elementUi to elementPlus, visible.sync is modified tov-model="visible"