Preface
Re-Alpha version of Vue 3.x. There should be Alpha, Beta and other versions in the future. It is expected that the official version of 3.0 will not be released until at least the first quarter of 2020.
So we should take advantage of the fact that we haven't yet come out to lay a good foundation for Vue2.x.
The basic usage of vue is easy to use, but you may not know many optimized ways of writing. This article lists 36 vue development techniques.
Continuous updates after Vue 3.x comes out.
1.require.context()
Scenario: If the page needs to import multiple components, the original writing:
import titleCom from '@/components/home/titleCom' import bannerCom from '@/components/home/bannerCom' import cellCom from '@/components/home/cellCom' components:{titleCom,bannerCom,cellCom}
2. This creates a lot of repetitive code that can be written using require.context
const path = require('path') const files = require.context('@/components/home', false, /\.vue$/) const modules = {} files.keys().forEach(key => { const name = path.basename(key, '.vue') modules[name] = files(key).default || files(key) }) components:modules
This method can be used regardless of how many components are introduced into the page.
3.API Method
In fact, it's a web pack approach. vue engineering is generally based on Web pack, so you can use it require.context(directory,useSubdirectories,regExp) Three parameters are received: directory: Describes the directories to be retrieved useSubdirectories: Whether to retrieve subdirectories regExp: A regular expression that matches a file, usually a file name
2.watch
2.1 Common Uses
Scenario: Initially the table comes in and needs to investigate the query interface getList(), and then the input change will be re-queried.
created(){ this.getList() }, watch: { inpVal(){ this.getList() } }
2.2 Immediate implementation
2. You can use watch's immediate and handler attributes to abbreviate directly
watch: { inpVal:{ handler: 'getList', immediate: true } }
2.3 Deep Monitoring
3.watch's deep attribute, deep listening, that is, listening for complex data types
watch:{ inpValObj:{ handler(oldVal,newVal){ console.log(oldVal) console.log(newVal) }, deep:true } }
It is found that the oldVal is the same as the newVal.
Because they index the same object/array, Vue does not retain a copy of the previous value.
So deep listening can monitor the change of the object, but it can't monitor the change of the attribute in the specific object.
3. 14 Kinds of Component Communication
3.1 props
This should be very attributes, that is, the attributes of the father and the son;
The props value can be an array or an object;
// Array: Not recommended props:[] // object props:{ type:Number, //Input Value Restriction Type // type values can be String,Number,Boolean,Array,Object,Date,Function,Symbol // type can also be a custom constructor and checked by instanceof required: true, //Is it necessary to pass on default:200, //Default values, object or array defaults must be obtained from a factory function such as default:() =>[] validator:(value) { // This value must match one of the following strings return ['success', 'warning', 'danger'].indexOf(value) !== -1 } }
3.2 $emit
This should also be very attributed, triggering custom events for parent components, which is actually the parent-descendant approach.
// Parent component <home @title="title"> // Subcomponents this.$emit('title',[{title:'This is title'}])
3.3 vuex
1. This is also very common. vuex is a state manager.
2. It's a separate plug-in, suitable for projects with more data sharing, because if it's just simple communication, it will be heavier to use.
3.API
State: Defines a warehouse for storing data that can be accessed through this.$store.state or mapState Getter: Gets the store value, which can be regarded as the computed attribute of the store, and can be accessed by this.$store.getter or mapGetters access Mutation: Synchronization changes store values, why is it designed to be synchronized, because mutation changes store values directly? vue records the operation, and if it is asynchronous, it cannot track the change. It can be invoked through mapMutations action: Asynchronously call a function to perform mutation and then change the store value by this.$dispatch or mapActions Visit Modules: Modules, if too many states, can be split into modules, and finally introduced at the entrance through... Deconstruction
3.4 $attrs and $listeners
2.4.0 Added
These two are uncommon attributes, but high-level usage is common.
1.$attrs
Scenario: If the parent and the child have many values, then multiple props need to be defined in the child component
Solution: $attrs gets values that are not defined in props in the child heir
// Parent component <home title="This is the title." width="80" height="80" imgUrl="imgUrl"/> // Subcomponents mounted() { console.log(this.$attrs) //{title:'This is the title', width:'80', height:'80', imgUrl:'imgUrl'} },
Correspondingly, if the subcomponent defines props, the printed value is to exclude the defined properties.
props: { width: { type: String, default: '' } }, mounted() { console.log(this.$attrs) //{title:'This is the title', height:'80', imgUrl:'imgUrl'} },
2.$listeners
Scenario: A child component needs to call a parent component's method
Solution: The parent component approach can be passed into the internal component via v-on="$listeners" -- very useful in creating higher-level components
// Parent component <home @change="change"/> // Subcomponents mounted() { console.log(this.$listeners) //You can get the change event }
If a grandchild component wants to access the attributes and invocation methods of its parent component, it can be passed down directly at the first level.
3.inheritAttrs
// parent component <home title= "This is the title" width= "80" height= "80" imgUrl= "imgUrl"/> // Subcomponents mounted() { Console.log (this. $attrs)/{title: "This is the title", "width:" 80","height:"80", "imgUrl:" imgUrl"} }, The default value of inheritAttrs is true, which means that the attributes on the parent component are displayed on the root component. If set to false, it will be hidden
3.5 provide and inject
2.2.0 Added
Description:
Provide and inject mainly provide use cases for high-level plug-in/component libraries. Direct use in application code is not recommended.
And this option needs to be used together.
To allow an ancestor component to inject a dependency into all its descendants, no matter how deep the component hierarchy is, and to remain in effect for the time when the upstream and downstream relationship is established.
//Parent component: provide: { //provide is an object that provides an attribute or method foo: 'This is foo', fooMethod:()=>{ console.log('Parent component fooMethod Called') } }, // Sons or grandchildren components inject: ['foo','fooMethod'], //Arrays or objects, injected into subcomponents mounted() { this.fooMethod() console.log(this.foo) } //inject is available to all child components under the parent component
The provide and inject bindings are not responsive. This was deliberately done by the authorities.
However, if you pass in a listenable object, its attributes are responsive, because the object is a reference type.
//Parent component: provide: { foo: 'This is foo' }, mounted(){ this.foo='This is new. foo' } // Sons or grandchildren components inject: ['foo'], mounted() { console.log(this.foo) //Does the subcomponent print'This is foo' }
3.6 $parent and $children
Parent: parent instance
children: Subinstance
//Parent component mounted(){ console.log(this.$children) //Attributes and methods for first-level subcomponents are available //So you can change the data directly, or call the methods method method } //Subcomponents mounted(){ console.log(this.$parent) //You can get parent attributes and methods }
$children and $parent do not guarantee order or responsiveness
Only first-level parent and child components are available
3.7 $refs
// Parent component <home ref="home"/> mounted(){ console.log(this.$refs.home) //You can get an instance of the sub-component, and you can directly manipulate data and methods. }
3.8 $root
// Parent component mounted(){ console.log(this.$root) //Get the root instance, and finally all components are mounted on the root instance console.log(this.$root.$children[0]) //Get the primary subcomponent of the root instance console.log(this.$root.$children[0].$children[0]) //Getting the secondary subcomponent of the root instance }
3.9 .sync
At vue@1.x, it existed as a bidirectional binding function, that is, the child component can modify the value in the parent component;
In vue@2.0, the design against a single data stream was abolished.
This. sync modifier was reintroduced in vue@2.3.0+and above.
// Parent component <home :title.sync="title" /> //When compiled, it will be extended to <home :title="title" @update:title="val => title = val"/> // Subcomponents // So subcomponents can be changed by triggering update method with $emit mounted(){ this.$emit("update:title", 'This is new title') }
3.10 v-slot
2.6.0 Added
1.slot,slot-cope,scope were discarded in 2.6.0, but not removed.
2. The function is to pass the template of the parent component into the child component.
3. Slot classification:
A. Anonymous slot (also known as default slot): No name, there is and only one;
// parent component <todo-list> <template v-slot:default> Arbitrary content <p> I'm an anonymous slot.</p> </template> </todo-list> // Subcomponents <slot>I am the default value </slot> // v-slot:default is more uniform in its sense of writing and its name is easy to understand, or it can be written without writing.
B. Named slots: relatively anonymous slot components with name tags;
// Parent component <todo-list> <template v-slot:todo> //Arbitrary content <p>I'm an anonymous slot. </p> </template> </todo-list> //Subcomponents <slot name="todo">I am the default</slot>
C. Scope slot: Data in a child component can be retrieved from the parent page (resolving that data can only be passed from the parent page to the child component)
// Parent component <todo-list> <template v-slot:todo="slotProps" > {{slotProps.user.firstName}} </template> </todo-list> //slotProps can be named at will //slotProps receives all v-bind:user="user" from the set of attribute data on the sub-component label slot // Subcomponents <slot name="todo" :user="user" :test="test"> {{ user.lastName }} </slot> data() { return { user:{ lastName:"Zhang", firstName:"yue" }, test:[1,2,3,4] } }, // {user.lastName}} is the default data v-slot:todo is not the parent page (= "slotProps")
3.11 EventBus
1. To declare a global Vue instance variable EventBus, which stores all communication data and event monitoring on this variable;
2. Similar to Vuex. But this approach applies only to very small projects.
3. The principle is to use $on and $emit and instantiate a global vue for data sharing.
// In main.js Vue.prototype.$eventBus=new Vue() // Value Passing Component this.$eventBus.$emit('eventTarget','This is eventTarget The value passed in') // Receiving component this.$eventBus.$on("eventTarget",v=>{ console.log('eventTarget',v);//This is the value passed from EvetTarget. })
4. Level and nested components can be implemented, but the corresponding event name EvetTarget must be globally unique.
3.12 broadcast and dispatch
vue 1.x has two methods, event broadcast and dispatch, but vue 2.x has been deleted
Here's the encapsulation of two methods
function broadcast(componentName, eventName, params) { this.$children.forEach(child => { var name = child.$options.componentName; if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { broadcast.apply(child, [componentName, eventName].concat(params)); } }); } export default { methods: { dispatch(componentName, eventName, params) { var parent = this.$parent; var name = parent.$options.componentName; while (parent && (!name || name !== componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.componentName; } } if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); } }, broadcast(componentName, eventName, params) { broadcast.call(this, componentName, eventName, params); } } }
3.13 Routing Reference
1. Programme I
// Routing Definition { path: '/describe/:id', name: 'Describe', component: Describe } // Page Reference this.$router.push({ path: `/describe/${id}`, }) // Page acquisition this.$route.params.id
2. Programme II
// Routing Definition { path: '/describe', name: 'Describe', omponent: Describe } // Page Reference this.$router.push({ name: 'Describe', params: { id: id } }) // Page acquisition this.$route.params.id
3. Programme III
// Routing Definition { path: '/describe', name: 'Describe', component: Describe } // Page Reference this.$router.push({ path: '/describe', query: { id: id `} ) // Page acquisition this.$route.query.id
4. Comparison of three schemes
Parametric page refresh after scheme 2 will be lost
One parameter of the scheme is stitched in the back, ugly and revealing information.
Scheme 3 will not splice parameters in the back and refresh parameters will not be lost.
3.14 Vue.observable
2.6.0 Added
Usage: Make an object responsive. Vue uses it internally to process objects returned by data functions.
The returned objects can be directly used in rendering functions and computational attributes, and the corresponding updates will be triggered when changes occur. It can also be used as minimal cross-component state memory for simple scenarios.
The principle of communication is essentially to realize a simple vuex by using Vue.observable
// File path - / store/store.js import Vue from 'vue' export const store = Vue.observable({ count: 0 }) export const mutations = { setCount (count) { store.count = count } } //Use <template> <div> <label for="bookNum">Number</label> <button @click="setCount(count+1)">+</button> <span>{{count}}</span> <button @click="setCount(count-1)">-</button> </div> </template> <script> import { store, mutations } from '../store/store' // Vue2.6 Added API Observable export default { name: 'Add', computed: { count () { return store.count } }, methods: { setCount: mutations.setCount } } </script>
4.render function
Scenario: Some of the code in the template will repeat a lot, so the render function will be useful at this time.
// Generate labels based on props // primary <template> <div> <div v-if="level === 1"> <slot></slot> </div> <p v-else-if="level === 2"> <slot></slot> </p> <h1 v-else-if="level === 3"> <slot></slot> </h1> <h2 v-else-if="level === 4"> <slot></slot> </h2> <strong v-else-if="level === 5"> <slot></slot> </stong> <textarea v-else-if="level === 6"> <slot></slot> </textarea> </div> </template> // Optimized version, using render function to reduce code repetition rate <template> <div> <child :level="level">Hello world!</child> </div> </template> <script type='text/javascript'> import Vue from 'vue' Vue.component('child', { render(h) { const tag = ['div', 'p', 'strong', 'h1', 'h2', 'textarea'][this.level] return h(tag, this.$slots.default) }, props: { level: { type: Number, required: true } } }) export default { name: 'hehe', data() { return { level: 3 } } } </script>
2. Contrast between render and template
The former is suitable for complex logic, while the latter is suitable for simple logic.
The latter belongs to declaration and rendering, while the former belongs to self-defined Render function.
The former has higher performance, while the latter has lower performance.
5. Asynchronous components
Scenario: Too large a project can lead to slow loading, so asynchronous component implementation on-demand loading is what must be done.
1. Asynchronous registration component
Three methods
// Factory functions perform resolve callbacks Vue.component('async-webpack-example', function (resolve) { // This particular `require'grammar will tell webpack // Automatically cut your build code into multiple packages // Load through Ajax request require(['./my-async-component'], resolve) }) // Factory function returns Promise Vue.component( 'async-webpack-example', // This `import'function returns a `Promise' object. () => import('./my-async-component') ) // Factory function returns a configurable component object const AsyncComponent = () => ({ // Components that need to be loaded (should be a `Promise'object) component: import('./MyComponent.vue'), // Components used when loading asynchronous components loading: LoadingComponent, // Components used when loading fails error: ErrorComponent, // Show the delay time of the component when loading. The default value is 200 (milliseconds) delay: 200, // If a timeout is provided and component loading is timed out, // The components used when the load fails are used. The default value is: `Infinity'.` timeout: 3000 })
The rendering of asynchronous components is essentially to perform rendering twice or more. First, the current component is rendered as a comment node. When the component is loaded successfully, the rendering is performed through forceRender. Or render it as a comment node and then as a loading node, rendering the component that is completed for the request
2. On-demand loading of routing
webpack< 2.4 Time { path:'/', name:'home', components:resolve=>require(['@/components/home'],resolve) } webpack> 2.4 Time { path:'/', name:'home', components:()=>import('@/components/home') } import()Method by es6 It is proposed that: import()The method is to load dynamically and return one Promise Objects, then The parameter of the method is the module loaded. Be similar to Node.js Of require Method, main import()The method is loaded asynchronously.
6. Dynamic components
Scenario: A tab switch involves dynamic loading of components
<component v-bind:is="currentTabComponent"></component>
But every time a component is reloaded, it consumes a lot of performance, so keep-alive works.
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
In this way, the switching effect has no animation effect, and there is no need to worry about it. The built-in <transition> can be used.
<transition> <keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive> </transition>
7. Recursive Components
Scenario: If you develop a tree component whose level is determined by background data, you need to use dynamic components at this time.
// Recursive Components: Components can recursively call themselves in their templates, as long as the name component is set to the component. // Setting up so that House can be used recursively in the component template, but it should be noted that, // A condition must be given to limit the number, otherwise an error will be thrown: max stack size exceeded // Component recursion is used to develop independent components with specific unknown hierarchical relationships. For example: // Joint selector and tree control <template> <div v-for="(item,index) in treeArr"> //Subcomponent, current hierarchical value: {{index} <br/> <!-- Recursive call itself, Background judgement whether there is no change in value --> <tree :item="item.arr" v-if="item.flag"></tree> </div> </template> <script> export default { // name must be defined for recursive invocation within a component name: 'tree', data(){ return {} }, // Receive external incoming values props: { item: { type:Array, default: ()=>[] } } } </script>
Recursive components must set name and end thresholds
8. Functional components
Definition: Stateless, unable to instantiate, without any lifecycle approach in-house
Rule: In versions prior to 2.3.0, the props option is required if a functional component wants to receive prop.
In versions 2.3.0 or above, you can omit the props option, and features on all components are automatically and implicitly resolved to prop. In versions 2.5.0 and above, if you use a single file component (that is, a normal. vue file), you can declare function directly on the template. Everything a component needs is passed through the context parameter
The context attribute has:
1.props: Provides all prop objects
2. Children: array of vnode children
3.slots: A function that returns the object containing all slots
4.scopedSlots: (2.6.0+) An object that exposes an incoming scoped slot. Normal slots are also exposed in the form of functions.
5.data: The entire data object passed to the component is passed into the component as the second parameter of the createElement
6.parent: Reference to parent components
7.listeners: (2.3.0+) An object that contains all event listeners registered by the parent component for the current component. This is an alias for data.on.
8.injections: (2.3.0+) If the inject option is used, the object contains attributes that should be injected
<template functional> <div v-for="(item,index) in props.arr">{{item}}</div> </template>
9.components and Vue.component
Components: Locally registered components
export default{ components:{home} }
Vue.component: Global Register Component
Vue.component('home',home)
10.Vue.extend
Scenario: Some elements in the vue component need to be mounted on the element, and extension works at this point.
Is a grammar that constructs a component
Writing:
// Create constructors var Profile = Vue.extend({ template: '<p>{{extendData}}</br>The data passed in by the instance is:{{propsExtend}}</p>',//The outer layer of the label corresponding to template must have only one label data: function () { return { extendData: 'This is extend Extended data', } }, props:['propsExtend'] }) // The constructor created can be mounted on elements or registered with components or Vue.component(). // Mounted on an element. It can be transmitted through propsData. new Profile({propsData:{propsExtend:'I am the data passed in by the instance.'}}).$mount('#app-extend') // Register through components or Vue.component() Vue.component('Profile',Profile)
11.mixins
Scenario: Some components have some repetitive js logic, such as checking mobile phone validation code, parsing time, etc., mixins can achieve this kind of mixing.
The mixins value is an array
const mixin={ created(){ this.dealTime() }, methods:{ dealTime(){ console.log('This is mixin Of dealTime Inside the method'); } } } export default{ mixins:[mixin] }
12.extends
Extensions is very similar to mixins in usage, except that the parameters received are simple option objects or constructors, so extends can only extend one component at a time.
const extend={ created(){ this.dealTime() }, methods:{ dealTime(){ console.log('This is mixin Of dealTime Inside the method'); } } } export default{ extends:extend }
13.Vue.use()
Scenario: When we use element, we import first, then Vue.use(), which is actually registering components and triggering the install method.
This is often used in component calls.
It automatically organizes multiple registrations of the same plug-in.
14.install
Scenario: In Vue.use(), executing this method triggers install
The first parameter of this method is the Vue constructor, and the second parameter is an optional option object (optional).
var MyPlugin = {}; MyPlugin.install = function (Vue, options) { // 2. Adding global resources, the second parameter passes a value corresponding to update by default. Vue.directive('click', { bind(el, binding, vnode, oldVnode) { //Prepare for binding, add time monitoring console.log('instructions my-directive Of bind Execution'); }, inserted: function(el){ //Get the bound element console.log('instructions my-directive Of inserted Execution'); }, update: function(){ //Perform corresponding updates based on the new values obtained //It will also be called once for the initial value. console.log('instructions my-directive Of update Execution'); }, componentUpdated: function(){ console.log('instructions my-directive Of componentUpdated Execution'); }, unbind: function(){ //Clean up //For example, event listeners that are bound when bind is removed console.log('instructions my-directive Of unbind Execution'); } }) // 3. Injection components Vue.mixin({ created: function () { console.log('Injected component created Called'); console.log('options The value is',options) } }) // 4. Adding Instance Method Vue.prototype.$myMethod = function (methodOptions) { console.log('Example method myMethod Called'); } } //Call MyPlugin Vue.use(MyPlugin,{someOption: true }) //3. Mounting new Vue({ el: '#app' });
Please stamp the operations of extend, mixins, extends, components, and install in vue for more details.
15. Vue.nextTick
2.1.0 Added
Scenario: Page loading requires text boxes to get focus
Usage: Delayed callbacks are performed after the end of the next DOM update cycle. Use this method immediately after modifying the data to obtain the updated DOM
mounted(){ //Because the mounted stage dom is not rendered, you need $nextTick this.$nextTick(() => { this.$refs.inputs.focus() //Get dom through $refs and bind the focus method }) }
16.Vue.directive
16.1 Use
Scenario: Officials have given us a lot of instructions, but if we want to turn text into a specified color and define instructions to use, we need to use Vue.directive at this time.
// Global Definition Vue.directive("change-color",function(el,binding,vnode){ el.style["color"]= binding.value; }) // Use <template> <div v-change-color>{{message}} </div> </template> <script> export default{ data(){ return{ color:'green' } } } </script>
16.2 Life Cycle
1.bind is invoked only once, when the instruction is first bound to an element. With this hook, you can define an initialization action to be performed once at the time of binding.
2. insert: Called when the bound element is inserted into the parent node (the parent node exists, but does not need to exist in the document)
3.update: Called when the binding is updated with the template where the element is located, and by comparing the binding values before and after the update, ignoring unnecessary template updates, regardless of whether the binding values have changed or not.
4. CompoonentUpdate: Called when the template of the bound element completes an update cycle
5.unbind: Called only once, when instructing the month element to unbind
17. Vue.filter
Scenario: Time stamp conversion to adult month day is a common method, so it can be extracted into filters for use
// Use // In double brackets {{ message | capitalize }} // In `v-bind' <div v-bind:id="rawId | formatId"></div> // Global registration Vue.filter('stampToYYMMDD', (value) =>{ // processing logic }) // Local registration filters: { stampToYYMMDD: (value)=> { // processing logic } } // Global registration of multiple filters // /src/common/filters.js let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3') export { dateServer } // /src/main.js import * as custom from './common/filters/custom' Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))
18.Vue.compile
Scenario: Compile Template Strings in render functions. Effective only when built independently
var res = Vue.compile('<div><span>{{ msg }}</span></div>') new Vue({ data: { msg: 'hello' }, render: res.render, staticRenderFns: res.staticRenderFns })
19.Vue.version
Scenario: Some development plug-ins need to be compatible with different vue versions, so Vue.version will be used.
Usage: Vue.version() can get vue version
var version = Number(Vue.version.split('.')[0]) if (version === 2) { // Vue v2.x.x } else if (version === 1) { // Vue v1.x.x } else { // Unsupported versions of Vue }
20.Vue.set()
Scenario: When you use an index to set an array item directly or when you modify the length of the array, the data is not updated responsively due to the limitation of the Object.defineprototype() method.
However, vue.3.x will use proxy to solve this problem.
Solution:
// Using set this.$set(arr,index,item) // Using array push(),splice()
21.Vue.config.keyCodes
Scenario: Custom key modifier alias
// Define keycode 113 as f2 Vue.config.keyCodes.f2 = 113; <input type="text" @keyup.f2="add"/>
22.Vue.config.performance
Scenario: listening performance
Vue.config.performance = true
Only for development patterns and browsers that support the performance.mark API
23.Vue.config.errorHandler
Scenarios: Processing functions that specify components that do not capture errors during rendering and observation
2. Rules:
Starting from 2.2.0, this hook also captures errors in the component lifecycle hook. Similarly, when the hook is undefined, the captured error is output through console.error to avoid application crash Since 2.4.0, this hook will also catch errors inside the Vue custom event handler. Starting from 2.6.0, this hook will also catch errors thrown inside the v-on DOM listener. In addition, if any overwritten hook or processing function returns a Promise chain (such as an async function), then errors from its Promise chain are also handled.
3. Use
Vue.config.errorHandler = function (err, vm, info) { // handle error // ` info ` is a Vue-specific error message, such as the life-cycle hook where the error is located // Only 2.2.0 + Available }
24.Vue.config.warnHandler
2.4.0 Added
Scenario: Give a custom handler for Vue runtime warnings, which only works in the developer environment
2. Usage:
Vue.config.warnHandler = function (msg, vm, trace) { // ` trace `is component inheritance tracing }
25.v-pre
Scenario: vue is a responsive system, but some static tags do not need to be compiled many times to save performance
<span v-pre> {this will not be compiled} </span> shows {this will not be compiled}} <span v-pre>{{msg} </span> Even if MSG is defined in data, {msg} is still displayed here.
26.v-cloak
Scenario: When using vue to bind data at a slow network speed, variable flicker occurs when rendering pages
Usage: This instruction remains on the element until the associated instance is compiled. When used with CSS rules such as [v-cloak] {display: none}, this instruction hides uncompiled Museache tags until the instance is ready
// In template <div class="#app" v-cloak> <p>{{value.name}}</p> </div> // In css [v-cloak] { display: none; }
This will solve the flicker, but there will be a white screen, which can be used in combination with the skeleton screen.
27.v-once
Scenario: Some template s have static dom unchanged, which only needs to be rendered once to reduce performance overhead
<span v-once> At this point, you only need to load the label once</span>
The difference between v-once and v-pre:
v-once renders only once; v-pre does not compile and outputs as it is
28. Event modifiers
stop: Prevent bubbles prevent: prevent default behavior self: Bind only the element itself to trigger once: 2.1.4 added, triggered only once Passive: Added 2.3.0, the default behavior of rolling events (i.e. rolling behavior) will be triggered immediately and cannot be used with. prevent
29. Key modifiers and key codes
Scenario: Sometimes you need to monitor the keyboard behavior, such as pressing enter to query the interface, etc.
// Corresponding keywords on keyboard .enter .tab Delete (capture delete and backspace keys) .esc .space .up .down .left .right
30.Vue-router
Scenario: Vue-router is an officially provided routing plug-in
30.1 Caching and Animation
Routing is the use of official component vue-router, the use of methods I believe you are very familiar with;
Here I will describe the routing cache and animation.
<transition> <keep-alive v-if="aliveFlag"> //Because some pages, such as trying data statistics, need to refresh in real time, so there is no need for caching. <router-view/> //Routing label </keep-alive> <router-view v-else/> </transition>
30.2 Global Routing Hook
1.router.beforeEach
router.beforeEach((to, from, next) => { console.log('Global Front Guard: beforeEach -- next Need to call') //This is commonly used for login interception, also known as navigation hook guard. if (path === '/login') { next() return } if (token) { next(); } })
2.router.beforeResolve (v 2.5.0+)
Similar to beforeEach, the difference is that the parsing guard is invoked before the navigation is validated and after the guard and asynchronous routing components in all components are parsed.
Called after beforeEach
3.router.afterEach
Global post hook
Called at the end of all routing hops
These hooks will not accept the next function nor change the navigation itself.
30.3 Component Routing Hook
1.beforeRouteEnter
Called before rendering the corresponding routing of the component is confirmed, the usage and parameters are similar to router. beforeeast, and next needs to be invoked actively
At this point, the component instance has not been created and cannot access this
Component instances can be accessed by passing a callback to next. Callbacks are performed when navigation is validated, and component instances are taken as parameters of the callback method
beforeRouteEnter (to, from, next) { // There is no access to the component instance, this === undefined next( vm => { // Accessing component instances through `vm' }) }
2.beforeRouteUpdate (v 2.2+)
When the current routing changes and the component is reused, the instance can be accessed through this. next needs to be invoked actively and cannot be called back.
3.beforeRouteLeave
Called when navigation leaves the corresponding routing of the component, component instance this can be accessed. next needs to be invoked actively and cannot be called back.
30.4 Routing Mode
Set the mode attribute: hash or history
30.5 Vue.$router
this.$router.push(): jump to different url s, but this method adds a record back to the history stack and clicks back to return to the previous page this.$router.replace(): No record this.$router.go(n):n can be positive or negative. Positive number returns to the previous page, similar to window.history.go(n)
30.6 Vue.$route
Represents the routing object that is currently jumping, with the following attributes:
Name: Route name
path: path
query: Reference Received Value
params: Reference Received Value
FulPath: Completed parsed URL with query parameters and the full path of hash
matched: copy of routing record
redirectedFrom: The name of the route for the redirected source if there is a redirection
this.$route.params.id: Gets parameters passed through params or /: ID this.$route.query.id: Gets parameters passed through query
30.7 router-view key
Scenario: Because Vue reuses the same components, i.e. / page / 1 = > / page / 2 or / page? Id = 1 = > / page? Id = 2, when a link jump is made, hooks such as created, mounted, etc. will not be executed.
<router-view :key="$route.fullpath"></router-view>
In this way, both created and mounted components will be executed.
31.Object.freeze
Scenario: A long list of data, usually unchanged, but vue does the conversion of getter and setter
Usage: A new feature of ES5 that freezes an object and prevents it from being modified
Support: vue 1.0.18 + supports it. For objects frozen with freeze in data or vuex, vue does not convert getter to setter.
Note: Freezing is just a single property inside the freeze, and the reference address can be changed.
new Vue({ data: { // vue does not bind object s in list s to getter or setter list: Object.freeze([ { value: 1 }, { value: 2 } ]) }, mounted () { // The interface will not respond because a single property is frozen this.list[0].value = 100; // In both cases, the interface responds. this.list = [ { value: 100 }, { value: 200 } ]; this.list = Object.freeze([ { value: 100 }, { value: 200 } ]); } })
32. Debugging template
Scenario: In the process of Vue development, you often encounter the problem of JavaScript variable error when template rendering. At this time, you may debug through console.log.
At this point, you can mount a log function in the development environment
// main.js Vue.prototype.$log = window.console.log; // Component internals <div>{{log(info)}}</div>
33.vue-loader tips
33.1 preserveWhitespace
Scenario: Developing vue code usually has spaces, at which time packing compression will increase the volume of the package if the spaces are not removed.
Configuring preserveWhitespace reduces package size
{ vue: { preserveWhitespace: false } }
33.2 transformToRequire
Scenario: In the past, when writing Vue, I used to write code like this: require the picture ahead of time to a variable and then to the component.
// page code <template> <div> <avatar :img-src="imgSrc"></avatar> </div> </template> <script> export default { created () { this.imgSrc = require('./assets/default-avatar.png') } } </script>
Now: by configuring transformToRequire, you can configure it directly, so that vue-loader will automatically require the corresponding properties and pass them to the component
// The default configuration of vue-cli 2.x in vue-loader.conf.js is transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } // Configuration file, if vue-cli2.x is modified in vue-loader.conf.js avatar: ['default-src'] // vue-cli 3.x in vue.config.js { vue: { transformToRequire: { avatar: ['default-src'] } } } // The page code can be simplified to <template> <div> <avatar img-src="./assets/default-avatar.png"></avatar> </div> </template>
34. Set aliases for paths
Scenario: In the development process, we often need to introduce various files, such as images, CSS, JS, etc. In order to avoid writing long relative paths (. /), we can configure an alias for different directories.
2.vue-cli 2.x configuration
// Add alias to the resolve configuration item in webpack.base.config.js resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } },
3.vue-cli 3.x configuration
// Create vue.config.js in the root directory var path = require('path') function resolve (dir) { console.log(__dirname) return path.join(__dirname, dir) } module.exports = { chainWebpack: config => { config.resolve.alias .set(key, value) // key,value defines itself, such as. set ('@', resolve ('src / components')) } }
35.img failed to load
Scene: Sometimes the background return image address may not be able to open, so a default image should be added at this time.
// page code <img :src="imgUrl" @error="handleError" alt=""> <script> export default{ data(){ return{ imgUrl:'' } }, methods:{ handleError(e){ e.target.src=reqiure('Picture Path') //Of course, if the project is configured with transformToRequire, refer to 27.2 above. } } } </script>
36.css
36.1 Local Style
1. The scoped attribute of style tag in Vue indicates that its style only acts on the current module and is style privatization.
2. Rules/Principles of Rendering:
Add a non-repetitive data attribute to the DOM node of HTML to represent uniqueness
Add a data attribute selector for the current component at the end of the corresponding CSS selector to privatize the style, such as:.demo[data-v-2311c06a] {}
If less or sass is introduced, it will only be set on the last element
// Original code <template> <div class="demo"> <span class="content"> Vue.js scoped </span> </div> </template> <style lang="less" scoped> .demo{ font-size: 16px; .content{ color: red; } } </style> // Browser rendering effect <div data-v-fed36922> Vue.js scoped </div> <style type="text/css"> .demo[data-v-039c5b43] { font-size: 14px; } .demo .content[data-v-039c5b43] { //There is no data attribute added to. demo color: red; } </style>
36.2 deep attribute
// Add A / deep to the above style/ <style lang="less" scoped> .demo{ font-size: 14px; } .demo /deep/ .content{ color: blue; } </style> // After compiling browser <style type="text/css"> .demo[data-v-039c5b43] { font-size: 14px; } .demo[data-v-039c5b43] .content { color: blue; } </style>
Afterword
The original codeword is not easy, welcome star!