preface
Vue 3. Pre Alpha version of X. There should be Alpha, Beta and other versions later. It is expected that the official version of 3.0 will not be released until the first quarter of 2020 at least;
So we should play vue2 before we come out The basis of X;
The basic usage of vue is easy to use, but there are many optimized writing methods that you may not know. This article lists 36 vue development skills;
Subsequent Vue 3 After X comes out, it will be updated continuously
1.require.context()
1. Scenario: if the page needs to import multiple components, the original writing method:
import titleCom from '@/components/home/titleCom' import bannerCom from '@/components/home/bannerCom' import cellCom from '@/components/home/cellCom' components:{titleCom,bannerCom,cellCom} Copy code
2. In this way, a lot of repeated code is written, using require Context can be written as
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 Copy code
In this way, this method can be used no matter how many components are introduced into the page
3.API method
Actually webpack Method of,vue Engineering is generally based on webpack,So you can use require.context(directory,useSubdirectories,regExp) Receive three parameters: directory: Describe the directory to retrieve useSubdirectories: Whether to check the subdirectory regExp: Regular expressions that match files,Usually the file name Copy code
2.watch
2.1 common usage
1. Scenario: the initial entry of the table needs to call the query interface getList(), and then the input will be changed to re query
created(){ this.getList() }, watch: { inpVal(){ this.getList() } } Copy code
2.2 immediate implementation
2. You can directly use the shorthand of the immediate and handler properties of watch
watch: { inpVal:{ handler: 'getList', immediate: true } } Copy code
2.3 deep monitoring
3. Deep attribute of watch, deep listening, that is, listening for complex data types
watch:{ inpValObj:{ handler(newVal,oldVal){ console.log(newVal) console.log(oldVal) }, deep:true } } Copy code
At this time, it is found that the values of oldVal and newVal are the same; Because they index the same object / array, Vue will not keep a copy of the value before modification; Therefore, although deep monitoring can monitor the changes of the object, it cannot monitor the changes of the attribute in the specific object
3. Communication of 14 components
3.1 props
This should be a special attribute, that is, the attribute passed from parent to child; props value can be an array or object;
// Array: not recommended props:[] // object props:{ inpVal:{ type:Number, //Incoming value qualified type // The type value can be String,Number,Boolean,Array,Object,Date,Function,Symbol // type can also be a custom constructor and checked and confirmed by instanceof required: true, //Is it necessary to pass default:200, //Default value. The default value of an object or array 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 } } } Copy code
3.2 $emit
This should also be very common. Triggering the child component to trigger the event bound by the parent component is actually the method of passing the child to the parent
// Parent component <home @title="title"> // Subcomponents this.$emit('title',[{title:'This is title'}]) Copy code
3.3 vuex
1. This is also very common. vuex is a state manager 2 It is an independent plug-in, which is suitable for projects with more data sharing, because if it is only simple communication, it will be more heavy to use. 3 API
state:Define the warehouse for storing data ,Can pass this.$store.state or mapState visit getter:obtain store value,Can be considered store Calculation properties of,Can pass this.$store.getter or mapGetters visit mutation:Synchronous change store value,Why is it designed to be synchronous,because mutation It's a direct change store value, vue The operation is recorded,If asynchronous, changes cannot be tracked.Can pass mapMutations call action:Asynchronous call function execution mutation,Then change store value,Can pass this.$dispatch or mapActions visit modules:modular,If there are too many states,Can be split into modules,Finally pass at the entrance...Deconstruction introduction Copy code
3.4 attrs and attrs and attrs and listeners
2.4.0 these two new attributes are not commonly used, but advanced usage is very common; 1.attrs scenario: if there are many values passed from the parent to the child, multiple props need to be defined in the child component for solution: attrs scenario: if there are many values passed from the parent to the child, multiple props need to be defined in the child component for solution: attrs scenario: if there are many values passed from the parent to the child, multiple props need to be defined in the child component for solution: attrs obtains the values not defined in props in the child parent
// 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"} }, Copy code
Correspondingly, if the subcomponent defines props, the printed value is to eliminate the defined attributes
props: { width: { type: String, default: '' } }, mounted() { console.log(this.$attrs) //{Title: "this is the title", height: "80", imgUrl: "imgUrl"} }, Copy code
2.listeners scenario: the sub component needs to call the method of the parent component: the method of the parent component can be solved through V − on="listeners scenario: the sub component needs to call the method of the parent component: the method of the parent component can be solved through v-on="listeners scenario: the sub component needs to call the method of the parent component: the method of the parent component can be passed into the internal component through V − on="listeners" - very useful when creating higher-level components
// Parent component <home @change="change"/> // Subcomponents mounted() { console.log(this.$listeners) //You can get the change event } Copy code
If a child component wants to access the properties and calling methods of the parent component, it can be passed down directly from one level to another
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"} }, inheritAttrs The default value is true,true It means that the parent component props Add attributes outside to the root node of the child component(Description, even if set to true,Subcomponents can still pass $attr Get props Unexpected attribute) take inheritAttrs:false after,The attribute will not be displayed on the root node Copy code
3.5 provide and inject
2.2.0 new description: provide and inject mainly provide use cases for high-level plug-in / component libraries. It is not recommended to use it directly in application code; And this pair of options need to be used together; To allow an ancestor component to inject a dependency into all its descendants, no matter how deep the component level is, and it will always take effect when the upstream and downstream relationship is established.
//Parent component: provide: { //provide is an object that provides a property or method foo: 'This is foo', fooMethod:()=>{ console.log('Parent component fooMethod Called') } }, // Child or grandson component inject: ['foo','fooMethod'], //Array or object, injected into sub components mounted() { this.fooMethod() console.log(this.foo) } //Under the parent component, all child components can use inject Copy code
The provide and inject bindings are not responsive. This was deliberately done by the authorities. However, if you pass in an object that can listen, the properties of the object are still responsive because the object is a reference type
//Parent component: provide: { foo: 'This is foo' }, mounted(){ this.foo='This is new foo' } // Child or grandson component inject: ['foo'], mounted() { console.log(this.foo) //The subcomponent prints' this is foo ' } Copy code
provide and inject response methods
// Parent component provide() { return { staticValue: this.staticValue, // Direct return value, unresponsive staticObject: this.staticObject, // Returns an object that can respond getReactiveValue: () => this.staticValue // Returns a function of an object that can respond to } }, // Subcomponents inject: ["staticValue", "getReactiveValue", "staticObject"], computed: { reactiveValue() { return this.getReactiveValue(); // Return the injected object function and listen for the change of value by calculating the attribute }, }, Copy code
Therefore, an object or function returned by provide can respond, because the object and function are reference types. In fact, the change is not vue done, but the reference type feature of JS
3.6 parent and parent and children
Parent: parent instance parent: parent instance parent: parent instance children: child instance
//Parent component mounted(){ console.log(this.$children) //You can get the properties and methods of the first level sub components //So you can change the data directly or call the methods method } //Subcomponents mounted(){ console.log(this.$parent) //You can get the properties and methods of the parent } Copy code
Children and children and children and parents do not guarantee the order and are not responsive. They can only get the first level parent and child components
3.7 $refs
// Parent component <home ref="home"/> mounted(){ console.log(this.$refs.home) //You can get the instance of the sub component and directly operate data and methods } Copy code
3.8 $root
// Parent component mounted(){ console.log(this.$root) //Get the root instance. Finally, all components are mounted on the root instance console.log(this.$root.$children[0]) //Gets the first level subcomponent of the root instance console.log(this.$root.$children[0].$children[0]) //Gets the secondary sub component of the root instance } Copy code
3.9 .sync
In vue@1.x It used to exist as a two-way binding function, that is, the child component can modify the value in the parent component; In vue@2.0 Because of violating the design of single data flow, it was killed; In vue@2.3.0+ This is reintroduced in the above version sync modifier;
// Parent component <home :title.sync="title" /> //At compile time, it will be extended to <home :title="title" @update:title="val => title = val"/> // Subcomponents // So the $emit method can be triggered by the update subcomponent mounted(){ this.$emit("update:title", 'This is new title') } Copy code
3.10 v-slot
2.6.0 add 1 Slot, slot copy and scope are all discarded in 2.6.0, but not removed 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): there is no name, and there is only one;
// Parent component <todo-list> <template v-slot:default> Any content <p>I'm anonymous </p> </template> </todo-list> // Subcomponents <slot>I'm the default</slot> //v-slot:default is written in a unified way with the named writing method, which is easy to understand and can also be omitted Copy code
B. Named slot: the slot tag of the relative anonymous slot component is named with name;
// Parent component <todo-list> <template v-slot:todo> Any content <p>I'm anonymous </p> </template> </todo-list> //Subcomponents <slot name="todo">I'm the default</slot> Copy code
C. Scope slot: the data in the sub component can be obtained by the parent page (solves the problem that the data can only be passed from the parent page to the sub component)
// Parent component <todo-list> <template v-slot:todo="slotProps" > {{slotProps.user.firstName}} </template> </todo-list> //slotProps can be named at will //slotProps receives the collection of attribute data on the sub component label slot. All v-bind:user="user" // 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. When the parent page does not (= "slotProps") Copy code
3.11 EventBus
1. Declare a global vue instance variable EventBus and store all communication data and event listening in this variable; 2. Similar to Vuex. But this method is only applicable to very small projects 3 The principle is to use on and on and on and emit and instantiate a global vue to realize data sharing
// In main js Vue.prototype.$eventBus=new Vue() // Value transfer component this.$eventBus.$emit('eventTarget','This is eventTarget Value passed') // Receiving component this.$eventBus.$on("eventTarget",v=>{ console.log('eventTarget',v);//This is the value passed from eventTarget }) Copy code
4. Horizontal and nested components can pass values, but the corresponding event name eventTarget must be globally unique
3.12 broadcast and dispatch
vue 1.x has two methods, event broadcast and dispatch, but Vue 2 X removes the following encapsulation of the 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); } } } Copy code
3.13 routing parameters
1. Programme I
// Route definition { path: '/describe/:id', name: 'Describe', component: Describe } // Page transfer parameter this.$router.push({ path: `/describe/${id}`, }) // Page acquisition this.$route.params.id Copy code
2. Programme II
// Route definition { path: '/describe', name: 'Describe', component: Describe } // Page transfer parameter this.$router.push({ name: 'Describe', params: { id: id } }) // Page acquisition this.$route.params.id Copy code
3. Programme III
// Route definition { path: '/describe', name: 'Describe', component: Describe } // Page transfer parameter this.$router.push({ path: '/describe', query: { id: id `} ) // Page acquisition this.$route.query.id Copy code
4. Comparison of the three schemes. The parameters of scheme 2 will not be spliced behind the route, and the page refresh parameters will be lost. The parameters of scheme 1 and scheme 3 are spliced behind, ugly and exposed information
3.14 Vue.observable
2.6.0 new usage: make an object responsive. Vue will use it internally to handle the objects returned by the data function; The returned objects can be directly used in rendering functions and calculation attributes, and will trigger corresponding updates when changes occur; It can also be used as a minimized cross component state memory for simple scenarios. The communication principle is essentially the use of Vue Observable implements a simple vuex
// 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">quantity</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. Add API Observable export default { name: 'Add', computed: { count () { return store.count } }, methods: { setCount: mutations.setCount } } </script> Copy code
4.render function
1. Scenario: some code written in the template will repeat a lot, so the render function works at this time
// Generate tags according to 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> // In the optimized version, the render function is used to reduce the 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-1] return h(tag, this.$slots.default) }, props: { level: { type: Number, required: true } } }) export default { name: 'hehe', data() { return { level: 3 } } } </script> Copy code
2. Comparison between Render and template: the former is suitable for complex logic, while the latter is suitable for simple logic; The latter belongs to the declaration of rendering, and the former belongs to the custom Render function; The former has higher performance and the latter has lower performance.
5. Asynchronous components
Scenario: too large a project will lead to slow loading, so asynchronous components must be loaded on demand. 1 Three methods of asynchronously registering components
// The factory function performs a resolve callback Vue.component('async-webpack-example', function (resolve) { // This special 'require' syntax will tell webpack // Automatically cut your build code into multiple packages // It will be loaded through Ajax request require(['./my-async-component'], resolve) }) // The factory function returns Promise Vue.component( 'async-webpack-example', // This' import 'function will return a' Promise 'object. () => import('./my-async-component') ) // The factory function returns a configurable component object const AsyncComponent = () => ({ // Component to be loaded (it 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 the component load also times out, // The component used when the load failed is used. The default is: ` Infinity` timeout: 3000 }) Copy code
In essence, the rendering of asynchronous components is to render two or more times. First render the current component as an annotation node. When the component is loaded successfully, re render it through forceRender. Or render it as an annotation node, and then render it as a loading node, and then render it as a requested component
2. On demand loading of routes
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 Put forward, import()The method is dynamic loading and returns a Promise Object, then Method is the module loaded into. be similar to Node.js of require Method, main import()Methods are loaded asynchronously. Copy code
6. Dynamic components
Scenario: dynamic loading of components will be involved when making a tab switch
<component v-bind:is="currentTabComponent"></component> Copy code
But in this way, the components will be reloaded every time, which will consume a lot of performance, so it works
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive> Copy code
In this way, the switching effect has no animation effect. There is no need to worry about this. You can use the built-in
<transition> <keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive> </transition> Copy code
7. Recursive component
Scenario: if a tree component is developed, its level is determined according to the background data, and dynamic components are needed at this time
// Recursive component: the component can call itself recursively in its template. Just set the name component to the component. // After setting, House can be used recursively in the component template, but it should be noted that, // A condition must be given to limit the quantity, or an error will be thrown: max stack size exceeded // Component recursion is used to develop some independent components with unknown hierarchical relationship. For example: // Inline selectors and tree controls <template> <div v-for="(item,index) in treeArr"> Sub component, current level value: {{index}} <br/> <!-- Recursive call itself, The background judges whether there is no value change --> <tree :item="item.arr" v-if="item.flag"></tree> </div> </template> <script> export default { // name must be defined to be called recursively inside the component name: 'tree', data(){ return {} }, // Receive external incoming values props: { item: { type:Array, default: ()=>[] } } } </script> Copy code
Recursive components must set thresholds for name and end
8. functional components
Definition: stateless, cannot be instantiated, and there is no internal life cycle processing method rule: in versions before 2.3.0, if a functional component wants to receive prop, the props option is required. In version 2.3.0 or above, you can omit the props option, and the features on all components will be automatically and implicitly resolved to prop. In version 2.5.0 or above, if you use a single file component (that is, an ordinary. vue file), you can directly declare the functional component on the template, and everything you need is passed through the context parameter
context attribute: 1 Props: provide objects of all prop s 2 Children: array of vnode child nodes 3 Slots: a function that returns an object containing all slots 4 Scopedslots: (2.6.0 +) an object that exposes the incoming scope slot. Ordinary slots are also exposed in the form of functions. 5.data: the entire data object passed to the component, which is passed into the component as the second parameter of createElement 6 Parent: reference to parent component 7 Listeners: (2.3.0 +) an object that contains all event listeners registered by the parent component for the current component. This is data An alias for on. 8.injections: (2.3.0+) if the inject option is used, the object contains the attributes that should be injected
<template functional> <div v-for="(item,index) in props.arr">{{item}}</div> </template> Copy code
9.components and Vue component
Components: locally registered components
export default{ components:{home} } Copy code
Vue.component: global registration component
Vue.component('home',home) Copy code
10.Vue.extend
Scenario: some vue components need to mount some elements to the elements. At this time, extend plays a role. It is the syntax of constructing a component:
// Create constructor var Profile = Vue.extend({ template: '<p>{{extendData}}</br>The data passed in by the instance is:{{propsExtend}}</p>',//The outermost layer of the label corresponding to template must have only one label data: function () { return { extendData: 'This is extend Extended data', } }, props:['propsExtend'] }) // The created constructor can be attached to the element, or through components or Vue Component() registered for use // Mount to an element. Parameters can be passed through propsData new Profile({propsData:{propsExtend:'I am the data passed in by the instance'}}).$mount('#app-extend') // Via components or Vue Component() registration Vue.component('Profile',Profile) Copy code
11.mixins
Scenario: some components have some duplicate js logic, such as checking the mobile phone verification code, parsing time, etc. mixins can realize this mixing. The mixins value is an array
const mixin={ created(){ this.dealTime() }, methods:{ dealTime(){ console.log('This is mixin of dealTime Inside method'); } } } export default{ mixins:[mixin] } Copy code
12.extends
The usage of extensions is very similar to mixins, except that the parameters received are simple option objects or constructors, so extensions can only extend one component at a time
const extend={ created(){ this.dealTime() }, methods:{ dealTime(){ console.log('This is mixin of dealTime Inside method'); } } } export default{ extends:extend } Copy code
13.Vue.use()
Scenario: when using element, we will first import and then Vue Use (), in fact, is to register the component and trigger the install method; This is often used in component calls; It will automatically organize to register the same plug-in multiple times
14.install
Scene: in vue Use () says that executing this method will trigger install, which is a plug-in for developing Vue. The first parameter of this method is Vue constructor, and the second parameter is an optional option object (optional)
var MyPlugin = {}; MyPlugin.install = function (Vue, options) { // 2. Add global resources. The second parameter passes a value. The default value is the value corresponding to update Vue.directive('click', { bind(el, binding, vnode, oldVnode) { //Make preparations for binding and add time monitoring console.log('instructions my-directive of bind Execute'); }, inserted: function(el){ //Get bound element console.log('instructions my-directive of inserted Execute'); }, update: function(){ //The corresponding update is performed according to the obtained new value //It is also called once for the initial value console.log('instructions my-directive of update Execute'); }, componentUpdated: function(){ console.log('instructions my-directive of componentUpdated Execute'); }, unbind: function(){ //Clean up //For example, the event listener bound when the bind is removed console.log('instructions my-directive of unbind Execute'); } }) // 3. Injection assembly Vue.mixin({ created: function () { console.log('Injection assembly created Called'); console.log('options The value of is',options) } }) // 4. Add instance method Vue.prototype.$myMethod = function (methodOptions) { console.log('Example method myMethod Called'); } } //Call MyPlugin Vue.use(MyPlugin,{someOption: true }) //3. Mount new Vue({ el: '#app' }); Copy code
For more information, please stamp several operations of extend, mixins, extends, components and install in vue
15. Vue.nextTick
2.1.0 new scenario: the text box needs to get the focus when the page is loaded. Usage: execute delayed callback after the next DOM update cycle. Use this method immediately after modifying the data to get the updated dom
mounted(){ //Because the dom in the mounted stage is not rendered, you need $nextTick this.$nextTick(() => { this.$refs.inputs.focus() //Get the dom through $refs and bind the focus method }) } Copy code
16.Vue.directive
16.1 use
Scenario: the official has provided us with many instructions, but if we want to change the text into a specified color to define the use of instructions, we need to use Vue directive
// Global definition Vue.directive("change-color",function(el,binding,vnode){ el.style["color"]= binding.value; }) // use <template> <div v-change-color="color">{{message}}</div> </template> <script> export default{ data(){ return{ color:'green' } } } </script> Copy code
16.2 life cycle
When the hook is bound to the. 1 instruction, it can be called only once. 2.inserted: called when the bound element is inserted into the parent node (it can be called if the parent node exists, and it does not have to exist in the document) 3 Update: called when the bound template is updated with the template where the element is located. No matter whether the binding value changes or not, by comparing the binding values before and after the update, unnecessary template updates are ignored. 4 Componentupdate: called when the template of the bound element completes an update cycle Unbind: called only once, when the instruction month element is unbound
17. Vue.filter
Scenario: time stamp is converted to month, year and day. This is a public method, so it can be extracted and used as a filter
// use // In double curly braces {{ 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])) Copy code
18.Vue.compile
Scenario: compile template string in render function. Valid only when built independently
var res = Vue.compile('<div><span>{{ msg }}</span></div>') new Vue({ data: { msg: 'hello' }, render: res.render, staticRenderFns: res.staticRenderFns }) Copy code
19.Vue.version
Scenario: some development plug-ins need to be compatible with different vue versions, so vue will be used Version usage: vue Version() can get the 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 } Copy code
20.Vue.set()
Scenario: when you use the index to directly set an array item or when you modify the length of the array, due to object The defineprototype () method limits that the data is not updated in response, but Vue 3. X will use proxy to solve this problem:
// Using set this.$set(arr,index,item) // Using array push(),splice() Copy code
21.Vue.config.keyCodes
Scene: custom key modifier alias
// Key code 113 is defined as f2 Vue.config.keyCodes.f2 = 113; <input type="text" @keyup.f2="add"/> Copy code
22.Vue.config.performance
Scenario: monitoring performance
Vue.config.performance = true Copy code
Only applicable to development mode and support performance Mark API browser
23.Vue.config.errorHandler
1. Scene: handler function that does not catch errors during rendering and observation of specified components 2 Rule: from 2.2.0, this hook will also catch errors in the component life cycle hook. Similarly, when the hook is undefined, the captured error will pass through the console Error output to avoid application crash. From 2.4.0, this hook will also catch the internal errors of Vue custom event handler. From 2.6.0, this hook will also catch the internal errors thrown by v-on DOM listener. In addition, if any overridden hook or processing function returns a Promise chain (such as async function), the error from its Promise chain will also be processed 3 use
Vue.config.errorHandler = function (err, vm, info) { // handle error // `info ` is Vue specific error information, such as the life cycle hook of the error // Available only in 2.2.0 + } Copy code
24.Vue.config.warnHandler
2.4.0 add 1 Scenario: assign a custom processing function to Vue's runtime warning, which will only take effect in the developer environment. 2 Usage:
Vue.config.warnHandler = function (msg, vm, trace) { // `Trace ` is the inheritance relationship trace of the component } Copy code
25.v-pre
Scenario: vue is a responsive system, but some static tags do not need to be compiled multiple times, which can save performance
<span v-pre>{{ this will not be compiled }}</span> It shows{{ this will not be compiled }} <span v-pre>{{msg}}</span> even if data It defines msg It is still shown here{{msg}} Copy code
26.v-cloak
Scene: in the case of slow network speed, when using vue to bind data, variable flicker will appear when rendering the page. Usage: this instruction remains on the element until the associated instance finishes compiling. When used with CSS rules such as [v-cloak] {display: none}, this instruction can hide the uncompiled Mustache tag until the instance is ready
// In template <div class="#app" v-cloak> <p>{{value.name}}</p> </div> // In css [v-cloak] { display: none; } Copy code
In this way, flickering can be solved, but a white screen will appear, which can be used in combination with the skeleton screen
27.v-once
Scene: some static DOMS in the template have not changed, so you only need to render once, which can reduce the performance overhead
<span v-once> You only need to load the label once</span> Copy code
The difference between v-once and v-pre: v-once only renders once; V-pre does not compile and outputs as is
28. Event modifier
.stop:Stop bubbling .prevent:Block default behavior .self:Triggered only by the binding element itself .once: 2.1.4 newly added,Trigger only once .passive: 2.3.0 newly added,Default behavior for scrolling events (Rolling behavior) Will be triggered immediately,Not with.prevent Use together Copy code
29. Key modifier and key code
Scenario: sometimes it is necessary to monitor the behavior of the keyboard, such as pressing enter to query the interface, etc
// Corresponding to the keyword on the keyboard .enter .tab .delete (Capture delete and backspace keys) .esc .space .up .down .left .right Copy code
30.Vue-router
Scenario: Vue router is an official routing plug-in
30.1 caching and animation
1. Routing uses the official component Vue router. I believe you are very familiar with the use method;
2. Here I will describe the cache and animation of routing;
3. You can use exclude (except) or include (including), and add 2.1.0 to judge
<transition> <keep-alive :include="['a', 'b']"> //Or include = "a, B": include = "/ a|b /", a and B represent the name of the component //Because some pages, such as data statistics, need to be refreshed in real time, so there is no need to cache <router-view/> //Routing label </keep-alive> <router-view exclude="c"/> // c represents the name value of the component </transition> Copy code
Note: first, check the name option of the component itself. If the name option is unavailable, match its local registered name (the key value of the parent component components option). Anonymous components cannot be matched
4. Judge with v-if, and the components will be re rendered, but there is no need to list the component name s one by one
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(); } }) Copy code
2.router.beforeResolve (v 2.5.0+) is similar to beforeEach. The difference is that before the navigation is confirmed, the guard is invoked after all the components are guarded and the asynchronous routing component is parsed, which is called after the beforeEach.
3.router. After each global post hook is called at the end of all route jumps. These hooks will not accept the next function and will not change the navigation itself
30.3 component routing hook
1.beforeRouteEnter calls before the corresponding routing of the component is rendered, usage and parameters and router. top note. Similar to beforeeach, next needs to be actively called. At this time, the component instance has not been created and cannot access this. You can access the component instance by passing a callback to next. Execute the callback when the navigation is confirmed, and take the component instance as the parameter of the callback method
beforeRouteEnter (to, from, next) { // The component instance cannot be accessed here. this === undefined next( vm => { // Access component instances through 'vm' }) } Copy code
2.beforeRouteUpdate (v 2.2 +) is called when the current route changes and the component is reused. You can access the instance through this. The next needs to be actively called and cannot send a callback
3.beforeRouteLeave is called when the navigation leaves the corresponding route of the component. You can access the component instance this. The next needs to be actively called and cannot send a callback
30.4 routing mode
Set the mode attribute: hash or history
30.5 Vue.$router
this.$router.push():Jump to a different url,But this method goes back history Add a record to the stack. Click back to return to the previous page this.$router.replace():There will be no record this.$router.go(n):n Can be positive or negative. Positive numbers go forward and negative numbers go back,similar window.history.go(n) Copy code
30.6 Vue.$route
Indicates the route object that is currently skipped. The attributes are: Name: route name path: path query: pass parameter receive value params: pass parameter receive value fullPath: the URL after parsing, including the full path of query parameters and hash. matched: copy of route record redirectedFrom: if there is redirection, it is the name of the route from which the redirection originates
this.$route.params.id:Get through params or/:id Parameters of parameter transmission this.$route.query.id:Get through query Parameters of parameter transmission Copy code
30.7 router view key
Scenario: because Vue will reuse the same components, i.e. / page / 1 = > / page / 2 or / page? id=1 => /page? When a link with id = 2 jumps, hooks such as created and mounted will not be executed
<router-view :key="$route.fullPath"></router-view> Copy code
In this way, both created and mounted components will be executed
31.Object.freeze
Scenario: a long list of data will not be changed, but vue will do the conversion of getter and setter. Usage: it is a new feature in ES5, which can freeze an object to prevent it from being modified. Support: vue 1.0.18 + provides support for it. For objects frozen by using free in data or vuex, vue will not do the conversion of getter and setter. Note: freezing only freezes a single attribute in it, and the reference address can still be changed
new Vue({ data: { // vue will not bind getter s and setter s to object s in the list list: Object.freeze([ { value: 1 }, { value: 2 } ]) }, mounted () { // The interface will not respond because individual properties are frozen this.list[0].value = 100; // In the following two ways, the interface will respond this.list = [ { value: 100 }, { value: 200 } ]; this.list = Object.freeze([ { value: 100 }, { value: 200 } ]); } }) Copy code
32. Debug template
Scenario: in the process of Vue development, you often encounter the problem of JavaScript variable error during template rendering. At this time, you may use console Log to debug. At this time, you can mount a log function in the development environment
// main.js Vue.prototype.$log = window.console.log; // Inside the component <div>{{$log(info)}}</div> Copy code
33. Vue loader tips
33.1 preserveWhitespace
Scenario: the development vue code usually has spaces. At this time, if the spaces are not removed, the volume of the package will be increased. Configuring preserveWhitespace can reduce the volume of the package
{ vue: { preserveWhitespace: false } } Copy code
33.2 transformToRequire
Scenario: in the past, when writing Vue, we often wrote such code: pass the picture to a variable in advance 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> Copy code
Now: after you configure transformToRequire, you can configure it directly. In this way, Vue loader will automatically require the corresponding attributes and then pass them to the component
// vue-cli 2.x in Vue loader The default configuration of conf.js is transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } // Configuration file, if vue-cli2 X in Vue loader Conf.js avatar: ['default-src'] // vue-cli 3.x in Vue config. js // vue-cli 3.x replace the transformToRequire attribute with transformAssetUrls module.exports = { pages, chainWebpack: config => { config .module .rule('vue') .use('vue-loader') .loader('vue-loader') .tap(options => { options.transformAssetUrls = { avatar: 'img-src', } return options; }); } } // The page code can be simplified to <template> <div> <avatar img-src="./assets/default-avatar.png"></avatar> </div> </template> Copy code
34. Set alias for path
1. Scenario: in the development process, we often need to introduce various files, such as pictures, 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
// On webpack base. config. JS, and add an alias in its alias resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }, Copy code
3.vue-cli 3.x configuration
// Create vue.exe in the root directory config. js 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 and value are defined by themselves, for example set('@@', resolve('src/components')) } } Copy code
35.img loading failed
Scene: sometimes the picture address returned from the background may not be opened, so a default picture 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 33.2 above } } } </script> Copy code
36.css
36.1 local style
1. The scoped attribute of the style tag in Vue indicates that its style only works on the current module, which is style privatization
2. Rendering rule / principle: add a non repeated data attribute to the DOM node of HTML to represent uniqueness, and add a data attribute selector of 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 effects <div data-v-fed36922> Vue.js scoped </div> <style type="text/css"> .demo[data-v-039c5b43] { font-size: 14px; } .demo .content[data-v-039c5b43] { //No data attribute is added to. demo color: red; } </style> Copy code
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 browser compilation <style type="text/css"> .demo[data-v-039c5b43] { font-size: 14px; } .demo[data-v-039c5b43] .content { color: blue; } </style>