Ten minutes, let you learn these clever cold skills of Vue

foreword


I have been writing Vue for two years, during which I have learned several techniques to improve development efficiency and performance. Now I summarize these techniques in the form of articles.

1. Use $attrs and $listeners


$attrs is used to record all the parameters passed into the child component from the parent component that are not captured by props and not class and style, while $listeners is used to record all the events passed in from the parent component without the .native modifier. The following code is an example:
Vue.component('child', {
props: ['title'],
template: '{{ title }}'
})

new Vue({
data:{a:1,title:'title'},
methods:{
handleClick(){
// ...
},
handleChange(){
// ...
}
},
template:'
',

})

then in

The value of attrs is {a:1,b:"1"}
The value of listeners is {change: handleChange}

Usually we can use $attrs and $listeners for component communication, which is more efficient when used in secondary package components, such as:
Vue.component("custom-dialog", {
// Inject the parameters and events passed by the parent component into the el-dialog instance through v-bind="$attrs" and v-on="$listeners"
template: '',
});

new Vue({
data: { visible: false },
// In this way, you can use visible to control the display and disappearance of custom-dialog like in el-dialog
template: '',
});

Another example:
Vue.component("custom-select", {
template: `


`,
});

new Vue({
data: { value: "" },
// v-model here is actually a combination of v-bind:value and v-on:change,
// In custom-select, through the injection of v-bind="$attrs" v-on="$listeners",
// Bind the value value on the parent component to the el-select in the custom-select component in both directions, which is equivalent to
// At the same time, the size variable injected in custom-select will also be injected into el-select through v-bind="$attrs" to control the size of el-select
template: '',
});

2. Use $props wisely
$porps is used to record all the parameters that are captured by props and not class and style passed from the parent component to the child component. like
Vue.component('child', {
props: ['title'],
template: '{{ title }}'
})

new Vue({
data:{a:1,title:'title'},
methods:{
handleClick(){
// ...
},
handleChange(){
// ...
}
},
template:'
',

})

Then in , the value of $props is {title:'title'}. $props can be used when the props defined by both the sub-component and the sub-component are the same, such as:
Vue.component('grand-child', {
props: ['a','b'],
template: '{{ a + b}}'
})

// When both child and grand-child need to use the values ​​of a and b from the parent component,
// In the child, you can quickly inject a and b into the grand-child through v-bind="$props"
Vue.component('child', {
props: ['a','b'],
template: `

The sum of {{a}} plus {{b}} is:


`
})

new Vue({
template:'
',
})

3. Magical use of functional components
The biggest difference between functional components and general vue components is that they are non-responsive. It doesn't listen to any data and has no instance (so no state, meaning no lifecycle like created, mounted). The advantage is that because it is just a function, the rendering overhead is also much lower.
Change the example at the beginning to a functional component, the code is as follows:


4. Magical use of Vue.config.devtools
In fact, we can also call vue-devtools to debug in the production environment, just change the Vue.config.devtools configuration, as shown below:
// Be sure to set the following synchronously immediately after Vue is loaded
// This configuration item defaults to `true` in the development version and `false` in the production version
Vue.config.devtools = true;

We can decide whether to enable this configuration item by detecting the user role information in the cookie, thereby improving the convenience of online bug finding.

5. Magical use of methods


A method in Vue can be assigned the result returned by a higher-order function, for example:


The above search function is assigned the result returned by debounce, that is, the request function with anti-shake function. This method can avoid that we have to write the anti-shake logic in the component by ourselves.
Here is an example sandbox, you can click it to see the difference between the method processed by the higher-order function and the original method, as shown below:

In addition, method can also be defined as a generator. If we have a function that needs to be executed in a very orderly manner, and we need to define variables in data to record the last state, we can consider using a generator.
For example, there is a very common scenario: when a WeChat video call is connected, a timer will be displayed to record the call time. This call time needs to be updated every second, that is, the function to obtain the call time needs to be executed every second. If it is written as ordinary The function needs to store the variable that records the time in data. But it can be solved neatly with generators, like this:




The page effect is as follows:

Code address: code sandbox
But it should be noted that: method cannot be an arrow function

Note that arrow functions should not be used to define method functions (eg plus: () => this.a++). The reason is that the arrow function is bound to the context of the parent scope, so this will not point to the Vue instance as expected and this.a will be undefined.

6. Magical use of watch's array format
Many developers will call multiple operations in the handler of a variable in the watch, as follows:


Although both fn1 and fn2 need to be called when the value changes, the calling timing of the two may be different. fn1 may only need to be called with deep false. Therefore, Vue adds the Array type to the value of watch to deal with the above situation. If the watch is Array, it can be written in the following form:


7. Magical use of $options
$options is an initialization property option that records the current Vue component. Usually in development, we want to reset a value in data to the value at the time of initialization, which can be written as follows:
this.value = this.$options.data().value;

In this way, when the initial value needs to be changed due to requirements, it can only be changed in the data.
Here is another scenario: there is an el-form in an el-dialog, and we require that the data in the el-form be reset every time the el-dialog is opened, we can write as follows:




Each time el-dialog is opened, the method initForm in its @open is called, thereby resetting the form value to the initial value. The effect is as follows:

The above code is placed in the sanbox
If you want to reset all the values ​​in data, you can write it like this:
Object.assign(this.$data, this.$options.data());
// Be careful not to write it like the following, which will change the point of this.$data. make it point to another state detached from the component
this.$data = this.$options.data();

8. Magical use of v-pre,v-once
v-pre
v-pre is used to skip the compilation process of the marked element and its sub-elements. If an element itself and its own elements are very heavy without any responsive logic related to Vue, then v-pre can be used to mark . After marking, the effect is as follows:

v-once

Render elements and components only once. Subsequent re-renders, the element/component and all its children will be treated as static content and skipped. This can be used to optimize update performance.

For some elements that will not have responsive changes after the first rendering, you can mark them with the v-once attribute, as follows:

v-for="item in options"
v-once
:key="item.value"
:label="item.label"
:value="item.value"
>{{i}}
>


If the variable options in the above example are large and there will be no responsive changes, then using v-once in the example will improve performance.

9. Magical use of hook events


If you want to monitor the life cycle of child components, you can do so as in the following example:


This way of writing can be used to handle the loading of third-party sub-components with a slightly longer initialization process, we can add loading animations, wait until the sub-components are loaded, and remove the loading animation when the mounted life cycle is reached.
In addition to the initial hook, there is a common way of writing. On a component that needs to poll for updated data, we usually start the timer in created, and then clear the timer in beforeDestroy. And through hooks, we can implement the logic of opening and destroying timers in created:


Writing like the above ensures the unity of logic and follows the principle of single responsibility.

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00