Properties on Vue instances

The component tree

  • $parent: The parent instance used to access the component instance
  • $root: to access the root instance of the current component tree
  • $children: A direct child component instance used to access the current component instance
  • $refs: a child component used to access the REF instruction

DOM access

  • $el: THE DOM element used to mount the current component instance
  • $els: to access the DOM element in the $el element that uses the V-el directive

The data access

  • $data: A data object used to access the component instance observation
  • $options: used to access the initialization option object when the component is instantiated

Use of DOM methods

  • $appendTo(elementOrSelector, callback): Inserts the DOM element referred to by el into the target element
  • $before(elementOrSelector, callback): Inserts the DOM element or fragment referred to by el before the target element
  • $after(elementOrSelector, callback): Inserts the DOM element or fragment referred to by el after the target element
  • $remove(callback): Removes the DOM element or fragment referred to by el from the DOM
  • $nextTick(callback): is used to execute the specified callback function after the next DOM update loop
// Vue's rendering process is asynchronous

<template>

<div id="app">

<p>{{text}}</p>

</div>

</template>

<script>

export default {

data() {

return {

text: 0

};

}

mounted(){

setInterval(()=> {

this.text +=1;

this.text +=1;

this.text +=1;

this.text +=1;

this.text +=1;

}, 1000).

}

}

</script>

Copy the code

You can see that the change in the text value is 0, 5, 10, 15… Instead of 0, 1, 2, 3… Continuous change like this

Use of the event method

1. Listening

  • $on(event, callback): Listens for custom events of the instance
  • $once(event, callback): Same as above, but can only trigger once
  • $watch(property,callback(new, old)): Listen for changes in the property and get the values before and after the change
// The first way

watch: {

text(new, old) {

The console. The log (` ${new} : ${old} `);

}

}

// The second way

const unWatch = this.$watch('text',(new,old)=>

The console. The log (` ${new} : ${old} `);

})

// unWatch is destroyed after 2 seconds

setTimeout(()=> {

unWatch();

}, 2000).



// Both methods have the same result, except that the second method requires manual destruction of $watch during component destruction

Copy the code

2. The trigger

  • $dispatch(event,args): dispatches events that are triggered at the current instance and then up the parent chain. The corresponding listener returns false to stop
  • $broadcast(event,args): broadcasts an event that iterates over $children of the current instance and stops if the corresponding listener returns false
  • $emit(event, args): Trigger event

3. Delete

  • $off(event, callback): Deletes time monitoring

4. Other

  • $forceUpdate(): Forces component refresh
  • $set(ele,attr,value): Sets properties for the object
  • $delete(ele,attr,value): Deletes object properties
<template>

<div id="app">

<p>{{obj.a}}</p>

</div>

</template>

<script>

export default {

data() {

return {

obj:{}

};

}

mounted(){

let i = 0;

setInterval(()=> {

i++;

/ / the first

this.obj.a = i ;

// If obj. A is not defined, vue cannot listen for this property, so the page value does not change. $forceUpdate can be used to force rendering

this.$forceUpdate();



/ / the second

this.$set(this.obj,'a',i);

}, 1000).

}

}

</script>

Copy the code

Vue life cycle

Vue official lifecycle

render (h) {

throw new TypeError('render error')

// console.log('render function invoked') // Render executes between beforeMount and mounted

// return h('div', {}, this.text) // virtual DOM

},

renderError (h, err) {

return h('div', {}, err.stack)

},

errorCaptured () {

// Bubbles up and can be used in formal environments

}

Copy the code

If you want to change a value in data, you can only do so in the CREATE life cycle

Vue data binding

<template>

<div id="app">

<p>{{isActive? 'active':'notActive'}}</p>

<p>{{arr.join(' ')}}</p>

<p>{{Date.now()}}</p>

<p v-html="html"></p>

<div

:class="{ active: isActive }"

:style="[styles, styles2]"

></div>

<div :class="[isActive? 'active':'']"></div>

<ul>

<li v-for="(item,index) in arr" :key="index">{{item}}</li>

</ul>



/ / a single checkbox

<input type="checkbox" v-model="a"> {{a}} <br/>

/ / multiple checkbox

<input type="checkbox" V-model ="b" value=" swim"

<input type="checkbox" V-model ="b" value=" float"

<input type="checkbox" V-model ="b" value=" swim "> sleep



<input type="radio" V-model ="c" value=" male "> Male

<input type="radio" V-model ="c" value=" female "> female



// Bind only once

<p v-once="a"></p>



</div>

</template>

<script>

export default {

data() {

return {

isActive: false,

arr: [1, 2, 3],

html: '<span>123</span>',

styles: {

color: 'red',

appearance: 'none'

},

styles2: {

color: 'black'

},

a: false,

B :[], // Get the checkbox value

C: "' / / gender

};

}

}

</script>

Copy the code

Modifier for v-model

Examples from the official website:

1.. Number If you want to automatically convert user input values to numeric types, you can add the number modifier to the V-Model:

<input v-model.number="age" type="number">

Copy the code

This is often useful because even when type= “number”, the value of the HTML input element always returns a string.

2.. Trim If you want to automatically filter out user input whitespace, you can add the trim modifier to v-Model:

<input v-model.trim="msg">

Copy the code

3.. Lazy By default, v-Model synchronizes the value of the input box with the data after each input event. You can change to synchronizing with the change event (when the input box loses focus) by adding the lazy modifier:

<! Update "change" instead of "input" -->

<input v-model.lazy="msg" >

Copy the code

Considerations for arrays and objects

An array of

Due to JavaScript limitations, Vue cannot detect the following altered arrays:

  • When you set an item directly using an index, for example, vm.items[indexOfItem] = newValue
  • When you modify the length of an array, for example, vm.items. Length = newLength
var vm = new Vue({

data: {

items: ['a', 'b', 'c']

}

})

Vm. items[1] = 'x' // Not responsive

Vm.items. Length = 2 // Not responsive

Copy the code

To solve the first type of problem, either of the following methods can achieve the same effect as vm.items[indexOfItem] = newValue, and also trigger a status update:

// Vue.set

Vue.set(vm.items, indexOfItem, newValue)

Copy the code
// Array.prototype.splice

vm.items.splice(indexOfItem, 1, newValue)

Copy the code

You can also use the vm.$set instance method, which is an alias for the global method vue. set:

vm.$set(vm.items, indexOfItem, newValue)

Copy the code

To solve the second type of problem, you can use Splice:

vm.items.splice(newLength)

Copy the code

object

Vue cannot detect the addition or deletion of object attributes:

var vm = new Vue({

data: {

a: 1

}

})

// 'vm.a' is now responsive



vm.b = 2

// 'vm.b' is not responsive

Copy the code

Vue cannot dynamically add root-level reactive properties to instances that have already been created. However, you can use the vue.set (Object, key, value) method to add responsive properties to nested objects. For example, for:

var vm = new Vue({

data: {

userProfile: {

name: 'Anika'

}

}

})

Copy the code

You can add a new age attribute to the nested userProfile object:

Vue.set(vm.userProfile, 'age', 27)

Copy the code

You can also use the vm.$set instance method, which is just an alias for the global vue. set:

vm.$set(vm.userProfile, 'age', 27)

Copy the code

Sometimes you may need to assign multiple new attributes to existing objects, such as object.assign () or _.extend(). In this case, you should create a new object with the properties of both objects. So, if you want to add new responsive attributes, don’t look like this:

Object.assign(vm.userProfile, {

age: 27,

favoriteColor: 'Vue Green'

})

Copy the code

Here’s what you should do:

vm.userProfile = Object.assign({}, vm.userProfile, {

age: 27,

favoriteColor: 'Vue Green'

})

Copy the code

Computed properties

Calculate the use of attributes

<template>

<div id="app">

<p>{{name}}</p>

</div>

</template>

<script>

export default {

data() {

return {

firstName: 'Fin',

lastName: 'Get',

};

},

computed: {

name() {

return `${this.firstName}${this.lastName}`

}

}

}

</script>

Copy the code

Bidirectional binding computes attributes with Vuex

// The vuex state cannot be modified directly. The official solution of the V-model is provided

<input v-model="message">



computed: {

message: {

get () {

return this.$store.state.obj.message

},

set (value) {

this.$store.commit('updateMessage', value)

}

}

}

Copy the code

If computed properties are used in a method or lifecycle, a set must be set

Watch the listener

Simple use of Watch

<div id="demo">{{ fullName }}</div>



var vm = new Vue({

el: '#demo',

data: {

firstName: 'Foo',

lastName: 'Bar',

fullName: 'Foo Bar'

},

Watch: {// When the watch method is originally bound, it will not be executed, only if it changes

firstName: function (val) {

this.fullName = val + ' ' + this.lastName

},

lastName: function (val) {

this.fullName = this.firstName + ' ' + val

}

}

})

Copy the code
watch: { 

// Declare a handler that will be executed once during initialization

firstName: {

handler(val) {

this.fullName = val + ' ' + this.lastName

},

immediate: true

}

}

Copy the code

Listen for changes in object properties

<div id="demo">{{ obj.a }}</div>

<input v-model="obj.a" />



var vm = new Vue({

el: '#demo',

data: {

obj: {

a: '123'

}

},

watch: {

obj: {

handler() {

console.log('obj.a changed');

},

immediate: true,

Deep: true // Obj. a changed will not be printed if you enter the value in the input field without this sentence

}

}

})

Copy the code
// This will allow you to listen for changes in property values

watch: {

'obj.a': {

handler() {

console.log('obj.a changed');

}

}

}

Copy the code

Vue components

Why must data in a Vue component be a function

Website to explain

In a Vue component data must be a function, but in new Vue() data can be an object

Vue.component('MyComponent', {

template: '<div>this is a component</div>',

data() {

Return {} // return a unique object. Do not share an object with other components

},

})

Copy the code

Here we define a MyComponent, which we can think of as a constructor. When a component is introduced and registered on another page, it is actually a reference to this constructor. Actually using a component in a template is like instantiating a component object.

// Let's simulate it

let MyComponent = function() {

// Define a constructor

}

MyComponent.prototype.data = {

name: 'component',

age: 0

}



// Instantiate the component object

let componentA = new MyComponent();

let componentB = new MyComponent();



componentA.data.name === componentB.data.name; // true

componentA.data.age = 4;

componentB.data.name;

Copy the code

As you can see, the data of two instance component objects are exactly the same, and one change will cause the other to change, which is not consistent with the idea of component in real development.

// Let's simulate it

let MyComponent = function() {

// Define a constructor

}

Functions have their own scope and do not affect each other

MyComponent.prototype.data = function() {

return {

name: 'component',

age: 0

}

}

Copy the code

Define global components with vue.use ()

// Define a button component

// button.vue

<template>

<div class="button">

button

</div>

</template>

<script>

</script>

Copy the code
// button.js

import ButtonComponent from './button.vue';

const Button={

install:function (Vue) {

Vue.component('Button',ButtonComponent)

}

}

export default Button;

Copy the code
// main.js

import Button from './component/button.js';

Vue.use(Button);

Copy the code

Vue.component(‘ button ‘,ButtonComponent), vuue. Use (button) You can also register global components directly in main.js using Vue.component().

props

<template>

<div class="button">

button

</div>

</template>

<script>

export default {

Props: [' MSG '], // No restrictions

// Input limits

props: {

// Basic type checking (' null 'matches any type)

propA: Number,

// Multiple possible types

propB: [String, Number],

// A mandatory string

propC: {

type: String,

required: true

},

// A number with default values

propD: {

type: Number,

default: 100

},

// Objects with default values

propE: {

type: Object,

// Object or array and must return default values from a factory function

default: function () {

return { message: 'hello' }

}

},

// Customize the validation function

propF: {

validator: function (value) {

This value must match one of the following strings

return ['success', 'warning', 'danger'].indexOf(value) ! = = 1

}

}

}

}

</script>

Copy the code

Subcomponents cannot modify props directly.

Communication issues between Vue components can be seen here…

Vue components extend

Using vue. extend constructs a “subclass” of the Vue constructor. Its argument is an object containing component options, where the data option must be a function.

import Vue from 'vue'



// An object containing component options

const compoent = {

props: {

active: Boolean,

propOne: String

},

template: `

<div>

<input type="text" v-model="text">

<span v-show="active">see me if active</span>

</div>

`,

data () {

return {

text: 0

}

},

Mounted () {// Print this mounted first

console.log('comp mounted');

}

}

// Create a subclass

const CompVue = Vue.extend(compoent);

// instantiate a subclass

new CompVue({

el: '#root',

PropsData: {// if we use props, we can't get values inside the component

propOne: 'xxx'

},

data: {

text: '123'

},

mounted () {

console.log('instance mounted');

}

})

Copy the code
const component2 = {

Extends: component, // Extends from component

data(){

return {

text: 1

}

},

mounted () {

this.$parent.text = '111111111'; // Can change the value of the parent component

console.log('comp2 mounted')

}

}



new Vue({

name: 'Root',

el: '#root',

mounted () {

console.log(this.$parent.$options.name)

},

components: {

Comp: componet2

},

data: {

text: 23333

},

template: `

<div>

<span>{{text}}</span>

<comp></comp>

</div>

`

})

Copy the code

Vue component advanced properties

Vue component slot

Slots are often used when you pass custom content into a component. Slots can contain any template code, including HTML or a component.

// Define a component with a slot

const component = {

name: 'comp',

template: `

<div>

<slot></slot>

</div>

`

}



new CompVue({

el: '#root',

components:{

Comp

},

template: `

<div>

<comp>

<p> The contents here are displayed in the slot </p>

</comp>

</div>

`

}

Copy the code

A named slot

Website links: cn.vuejs.org/v2/guide/co…

<div class="container">

<header>

<! -- We want to put the header here -->

<slot name="header"></slot>

</header>

<main>

<! -- We want to put the main content here -->

<slot name="main"></slot>

</main>

<footer>

<! -- We want to put footer here -->

<slot name="footer"></slot>

</footer>

</div>

Copy the code

Use of named slots:

First: Use the slot feature on the

<base-layout>

<template slot="header">

<h1>Here might be a page title</h1>

</template>



<template slot="main">

<p>A paragraph for the main content.</p>

<p>And another one.</p>

</template>



<template slot="footer">

<p>Here's some contact info</p>

</template>

</base-layout>

Copy the code

Second: use it directly on normal elements

<base-layout>

<h1 slot="header">Here might be a page title</h1>



<div slot="main">

<p>A paragraph for the main content.</p>

<p>And another one.</p>

</div>



<p slot="footer">Here's some contact info</p>

</base-layout>

Copy the code

The default contents of the slot

A default content can be set in the slot, and if the user does not set new content, the default content will be displayed

<button>

< slot > submit < / slot >

</button>

Copy the code

Scope slot

2.1.0+ added in 2.5.0+, slot-scope is no longer limited to

const component = {

name: 'comp',

template: `

<div>

<slot value="456" name="finget"></slot>

</div>

`

}



new CompVue({

el: '#root',

components:{

Comp

},

template: `

<div>

<comp>

<p slot-scope="props">{{props.value}} {{props.name}}</p> // 456 finget

</comp>

</div>

`

}

Copy the code

Provide/Inject cross-level component interaction

2.2.0 new

This pair of options needs to be used together to allow an ancestor component to inject a dependency into all of its descendants, regardless of how deep the component hierarchy is, and remain in effect as long as the upstream and downstream relationship is established.

// Parent component provides 'foo'

var Provider = {

provide: {

foo: 'bar'

},

// ...

}



// Inject 'foo' into the subcomponent

var Child = {

inject: ['foo'],

created () {

console.log(this.foo) // => "bar"

}

// ...

}

Copy the code

If you are injecting a value inside a parent component, provide needs to be a function, similar to data

const component = {

name: 'comp',

inject: ["value"]

template: `

<div> subcomponent {{value}}</div>

`

}



new CompVue({

el: '#root',

data() {

return {

value: '123'

}

}

components:{

Comp

},

Provide () {// There is no way to get this.value if it is only an object

return {

value: this.value

}

},

template: `

<div>

<comp></comp>

<input type="text" v-model="value">

</div>

`

}

Copy the code

If you want to listen for changes in the property values of the parent component to automatically update the values of the child components, you need to implement manual listening

const component = {

name: 'comp',

inject: ["data"]

template: `

<div> subcomponent {{data.value}}</div>

`

}



.

provide() {

const data = {}

// This is the basis of vUE bidirectional binding

Object.defineProperty(data,"value",{

get: () => this.value,

enumerable: true

})

return {

data

}

},

.

Copy the code

The Vue render

Vue template parsing: finget. Making. IO / 2018/05/31 /…

Vue-router

Router Build options

The redirection:

{

path: '/',

redirect: '/app'

}

Copy the code

The History mode:

const router = new VueRouter({

mode: 'history',

routes: [...]

})

Copy the code

Vue-router defaults to hash mode — the hash of a URL is used to simulate a full URL so that the page does not reload when the URL changes.

However, this mode to play well, but also need background configuration support. Because our application is a single-page client application, if the background is not properly configured, when the user accesses oursite.com/user/id directly from the browser, it will return 404, which is not pretty.

Give a warning page:

const router = new VueRouter({

mode: 'history',

routes: [

{ path: '*', component: NotFoundComponent }

]

})

Copy the code

base

const router = new VueRouter({

mode: 'history',

base: '/base/',

routes: [

{ path: '/hello', component: hello }

]

})

Copy the code

When accessing localhost: 8080 / hello becomes localhost: 8080 / base/hello, all the routing path will add/base, manually delete/base, of course, still can open the page

LinkActiveClass and linkExactActiveClass

<router-link to="/app">app</router-link>

<router-link to="/login">login</router-link>

Copy the code

Router-link is rendered as an A tag on the page. When clicked, two class names are added :router-link-exact-active and router-link-Active

const router = new VueRouter({

linkActiveClass: 'active-link',

linkExactActiveClass: 'exact-active-link'

})

Copy the code

This is like renaming two class names.

Differences between the two:

<router-link to="/login">login</router-link>

<router-link to="/login/exact">login exact</router-link>

Copy the code

Part of /login is the same between the two routes. Click login exact to switch to /login/exact.

/loginIt’s still thererouter-link-activeThe name of the class

scrollBehavior

With front-end routing, you want the page to roll to the top when switching to a new route, or to keep the original scrolling position, as if the page were being reloaded.

Note: This feature is only available in browsers that support history.pushState.

const router = new VueRouter({

scrollBehavior(to, form, savedPosition){

if (savedPosition) {

return savedPosition

} else {

return { x: 0, y: 0 }

}

},

routes: [...]

})

Copy the code

The scrollBehavior method receives to and FROM routing objects. The third parameter savedPosition is available if and only if popState navigation (triggered by the browser’s forward/back buttons).

ParseQuery and stringifyQuery

Provides parsing/antiparsing functions for custom query strings. Override the default behavior.

const router = new VueRouter({

parseQuery (query) {

console.log(query)

},

stringifyQuery (obj) {

console.log(obj)

}

})

Copy the code

fallback

PushState controls whether a route should revert to hash mode if the browser does not support history.pushState. The default value is true.

In IE9, setting it to false causes each router-link navigation to trigger a full page refresh. It can be used with server rendering applications working under IE9, because a HASH mode URL does not support server rendering.

const router = new VueRouter({

fallback: true

})

Copy the code

Routing meta information

Official website example:

const router = new VueRouter({

routes: [

{

path: '/foo',

component: Foo,

children: [

{

path: 'bar',

component: Bar,

// a meta field

meta: { requiresAuth: true }

}

]

}

]

})

Copy the code

So how do you access this META field?

First, we call each routing object in the Routes configuration a routing record. Routing records can be nested. Therefore, when a route is matched successfully, it may match multiple routing records

For example, according to the route configuration above, the URL /foo/bar will match the parent and child routing records.

All routes matched by a route are exposed as the $Route object (and the route object in the navigator) in the $Route. matched array. Therefore, we need to traverse $route.matched to check the META field in the routing record.

The following example shows checking meta fields in a global navigator:

router.beforeEach((to, from, next) => {

if (to.matched.some(record => record.meta.requiresAuth)) {

// this route requires auth, check if logged in

// if not, redirect to login page.

if (! auth.loggedIn()) {

next({

path: '/login',

query: { redirect: to.fullPath }

})

} else {

next()

}

} else {

Next () // Make sure you call next()

}

})

Copy the code

Named view

Displaying multiple view components under a route is not often done

// There are three separate views to present on this page

<router-view></router-view> // Default

<router-view name="a"></router-view> // View A

<router-view name="b"></router-view> // View B

Copy the code
const router = new VueRouter({

routes: [

{

path: '/',

Components: {// add s

Default: Foo, // corresponds to the default router-view

a: Bar, // name = "a"

b: Baz // name = "b"

}

}

]

})

Copy the code

Navigation guard

Hook functions that are triggered sequentially when a route changes

Global guard

const router = new VueRouter({ ... })



router.beforeEach((to, from, next) => {

console.log('before each invoked');

next();

})

router.beforeResolve((to, from, next) => {

console.log('before resolve invoked');

next();

})

Copy the code

Each guard method takes three arguments:

  • To: Route: indicates the destination Route to be entered

  • From: Route: Indicates the Route object that the current navigation is leaving

  • Next: Function: Be sure to call this method to resolve the hook. The execution depends on the call parameters of the next method.

    • Next (): Goes to the next hook in the pipe. If all hooks are executed, the navigation state is confirmed.

    • Next (false): interrupts current navigation. If the browser URL changes (either manually by the user or by the browser back button), the URL is reset to the address corresponding to the FROM route.

    • Next (‘/’) or next({path: ‘/’}): jumps to a different address. The current navigation is interrupted and a new navigation is performed. You can pass any location object to next, and you can set options like replace: True, name: ‘home’, and any options used in router-link’s to prop or router.push.

    • Next (error): (2.4.0+) If the argument passed to Next is an error instance, the navigation is terminated and the error is passed to the callback registered with router.onerror ().

Make sure you call the next method or the hook won’t be resolved.

Route objects

A Route object represents the status information of the currently activated route, including the information obtained from the current URL resolution and the Route records matched by the URL.

Route objects are immutable, and a new object is created after each successful navigation.

Route object properties:

  • $route.path

    • Type: string Indicates the path of the current route. It is always resolved to an absolute path, for example, /foo/bar.
  • $route.params

    • Type: Object A key/value Object that contains dynamic fragments and fully matched fragments, and is empty if there are no routing parameters.
  • $route.query

    • Type: Object A key/value Object representing URL query parameters. For example, for path /foo? $route.query.user == 1; $route.query.user == 1;
  • $route.hash

    • Type: string Hash value (with #) of the current route, empty if there is no hash value.
  • $route.fullPath

    • Type: string The parsed URL, which contains the query parameters and the full hash path.
  • $route.matched

    • Type: Array An Array containing the routing records of all nested path segments of the current route. The routing record is a copy of the objects in the Routes configuration array (and in the Children array).
const router = new VueRouter({

routes: [

// The following object is the routing record

{ path: '/foo', component: Foo,

children: [

// This is also a routing record

{ path: 'bar', component: Bar }

]

}

]

})

Copy the code

When the URL is /foo/bar, $route.matched will be a copy containing all objects from top to bottom.

  • $route.name Specifies the name of the current route, if any. (View named routes)

  • $route.redirectedFrom Specifies the name of the route from which the source is redirected, if any

Global post-hook

router.afterEach((to, from) => {

console.log('after each invoked');

})

Copy the code

Route exclusive guard

const router = new VueRouter({

routes: [

{

path: '/foo',

component: Foo,

beforeEnter: (to, from, next) => {

// ...

}

}

]

})

Copy the code

Guards within components

const Foo = {

template: `... `,

beforeRouteEnter (to, from, next) {

// called before the corresponding route to render the component is confirmed

/ / no! Can!!!! Get component instance 'this'

// Because the component instance has not been created before the guard executes

},

beforeRouteUpdate (to, from, next) {

// Called when the current route changes but the component is being reused

// For example, for a path /foo/:id with dynamic parameters, when jumping between /foo/1 and /foo/2,

// Since the same Foo component will be rendered, the component instance will be reused. And the hook will be called in that case.

// Access component instance 'this'

},

beforeRouteLeave (to, from, next) {

// called when navigating away from the component's corresponding route

// Access component instance 'this'

}

}

Copy the code

The beforeRouteEnter guard cannot access this because the guard is called before navigation confirmation, so the upcoming new component has not yet been created.

However, you can access the component instance by passing a callback to Next. The callback is executed when the navigation is validated, and the component instance is taken as an argument to the callback method.

beforeRouteEnter (to, from, next) {

next(vm => {

// Access component instances through 'VM'

})

}

Copy the code

Complete navigation parsing process

  1. Navigation is triggered.
  2. Call the leave guard in the inactivated component.
  3. Call globalbeforeEachThe guards.
  4. Called in a reused componentbeforeRouteUpdateGuard (+ 2.2).
  5. Called in the routing configurationbeforeEnter.
  6. Parse the asynchronous routing component.
  7. Called in the active componentbeforeRouteEnter.
  8. Call globalbeforeResolveGuard (+ 2.5).
  9. Navigation confirmed.
  10. Call globalafterEachHook.
  11. The triggerDOMThe update.
  12. Call with the created instancebeforeRouteEnterGuard passnextThe callback function of.

Asynchronous routing

In routing files, importing all components directly results in a longer first page rendering time, asynchronous routing, and loading of the corresponding page only when the corresponding route is entered.

const router = new VueRouter({

routes: [

{ path: '/foo',

component: () => import('.. /view/... '),

}

]

})

Copy the code

This requires syntax-dynamic-import to be installed and configured in.babelrc

// .babelrc

{

"plugins": ["syntax-dynamic-import"]

}

Copy the code

Vux

The following content from the website: https://vuex.vuejs.org/zh/

Simply use Vuex

// store.js

import Vuex from 'vuex'

import Vue from 'vue'



Vue.use(Vuex)



const store = new Vuex.Store({

state: {

count: 0

},

mutations: {

updateCount(state, num) {

state.count = num

}

}

})



export default store

Copy the code
// main.js

import Vue from 'vue'

import App from './App'

import store from './store/store.js'

Vue.config.productionTip = false



/* eslint-disable no-new */

new Vue({

el: '#app',

Store, / / a mount

components: { App },

template: '<App/>'

})

Copy the code
// Any component

mounted(){

console.log(this.$store)

let i = 1

setInterval(() => {

this.$store.commit('updateCount', i++)

})

},

computed: {

count() {

return this.$store.state.count

}

}

Copy the code

The core concept

State

Vuex uses a single state tree — yes, it contains all the application-level state in a single object. At this point it exists as a “unique data source (SSOT)”. This also means that each app will contain only one Store instance. A single state tree allows us to directly locate any particular state fragment and easily take a snapshot of the entire current application state during debugging.

State is a global object. After Vuex is registered globally with vue. use(Vuex), this.$store.state is available in any component

Vuex’s state store is reactive, and the easiest way to read state from a Store instance is to return some state in a calculated property.

computed: {

count() {

return this.$store.state.count

}

}

Copy the code

When count in State changes, computed is automatically updated to change the relevant DOM

MapState helper function

When a component needs to fetch multiple states, it can be repetitive and redundant to declare all those states as computed properties. To solve this problem, we can use the mapState helper function to help us generate calculated properties that will save you from pressing the key:

// In the separately built version, the auxiliary function is vuex.mapstate

import { mapState } from 'vuex'



export default {

// ...

computed: mapState({

// Arrow functions make code more concise

count: state => state.count,



// Pass the string argument 'count' equal to 'state => state.count'

countAlias: 'count',



// To be able to use 'this' to get local state, you must use regular functions instead of arrow functions

countPlusLocalState (state) {

return state.count + this.localCount

}

})

}

Copy the code

We can also pass mapState an array of strings when the name of the computed property of the map is the same as the name of the child node of State.

computed: mapState([

// Map this.count to store.state.count

'count'

])



// Common operations

computed: {

. mapState(['count'])

}



// Change the variable name

computed: {

. mapState({

count1 : 'count',

count2 : state => state.count

})

}

Copy the code

Getter

A Getter is a computed version of state of VUex. New states are derived from state, and they are cached and recalculated only when dependent states change

export default {

FullName (state) {// Accepts state as the first argument by default

return `${state.firstName}${state.lastName}`

}

}

Copy the code
MapGetters helper function

Getters are used similarly to state; you can use them as state.

import { mapGetters } from 'vuex'



export default {

// ...

computed: {

// Mix getters into a computed object using the object expansion operator

. mapGetters([

'doneTodosCount',

'anotherGetter',

// ...

])

}

}

Copy the code

If you want to change the name of the getter, the method is the same as state

Mutation

Mutation must be synchronous

The only way to change the state in Vuex’s store is to commit mutation. Mutations in Vuex are very similar to events: each mutation has a string event type (type) and a callback function (handler). This callback is where we actually make the state change, and it takes state as the first argument:

const store = new Vuex.Store({

state: {

count: 1

},

mutations: {

increment (state) {

// Change the state

state.count++

}

}

})

Copy the code

You cannot call a mutation handler directly. This option is more like event registration: “This function is called when a mutation of type INCREMENT is triggered.” To wake up a mutation handler, you need to call the store.mit method with the corresponding type:

store.commit('increment')

Copy the code
Load delivery (parameter transfer)

You can pass an additional parameter, payload, to store.mit:

// ...

mutations: {

increment (state, n) {

state.count += n

}

}



store.commit('increment', 10)

Copy the code

In most cases, the payload should be an object, which can contain multiple fields and the mutation recorded will be more readable:

// ...

mutations: {

increment (state, payload) {

state.count += payload.amount

}

}

store.commit('increment', {

amount: 10

})

Copy the code
Object style submission

Another way to submit mutation is to use an object containing the type attribute directly:

store.commit({

type: 'increment',

amount: 10

})

Copy the code

When using an object-style commit, the entire object is passed as a payload to the mutation function, so the handler remains unchanged:

mutations: {

increment (state, payload) {

state.count += payload.amount

}

}

Copy the code
Replace Mutation event types with constants

Substituting constants for mutation event types is a common pattern in various Flux implementations. This allows tools like Linter to work, and keeping these constants in a separate file allows your code collaborators to see what mutations are included in the entire app:

// mutation-types.js

export const SOME_MUTATION = 'SOME_MUTATION'

// store.js

import Vuex from 'vuex'

import { SOME_MUTATION } from './mutation-types'



const store = new Vuex.Store({

state: { ... },

mutations: {

// We can use ES2015 style computed attribute naming to use a constant as the function name

[SOME_MUTATION] (state) {

// mutate state

}

}

})

Copy the code
Commit Mutation in the component

You can use this. codeStore.mit (‘ XXX ‘) to commit mutation in the component, or use the mapMutations helper function to map methods in the component to a store.mit call (requiring store injection at the root node).

import { mapMutations } from 'vuex'



export default {

// ...

methods: {

. mapMutations([

'increment', // Map 'this.increment()' to 'this.store.com MIT ('increment')'



// 'mapMutations' also supports payloads:

'incrementBy' // Maps' this.incrementBy(amount) 'to' this. codestore.com MIT ('incrementBy', amount) '

]),

. mapMutations({

Add: 'increment' // Map 'this.add()' to 'this.add()' as' this. store.com MIT ('increment') '

})

}

}

Copy the code

Action

Actions can contain asynchronous operations

The Action is similar to Mutation. The Action commits the Mutation by calling the COMMIT method.

const store = new Vuex.Store({

state: {

count: 0

},

mutations: {

increment (state) {

state.count++

}

},

actions: {

increment (context) {

context.commit('increment')

}

}

})

Copy the code

The Action function accepts a context object with the same methods and properties as the store instance, so you can submit a mutation by calling context.mit. Or get state and getters via context.state and context.getters.

In practice, we’ll often use ES2015 parameter deconstruction to simplify code (especially if we need to call commit many times) :

actions: {

// {commit} = context

increment ({ commit }) {

commit('increment')

}

}

Copy the code

Actual code:

Distribute the Action in the component

You use this.$store.dispatch(‘ XXX ‘) to distribute actions in the component, or use the mapActions helper function to map the component’s methods to a store.dispatch call (which requires injecting store at the root node first) :

import { mapActions } from 'vuex'



export default {

// ...

methods: {

. mapActions([

'increment', // Map 'this.increment()' to 'this.$store.dispatch('increment')'



// 'mapActions' also supports payloads:

'incrementBy' // map 'this.incrementBy(amount)' to 'this.$store.dispatch('incrementBy', amount)'

]),

. mapActions({

Add: 'increment' // Map 'this.add()' to 'this.$store.dispatch('increment')'

})

}

}

Copy the code

Strict mode

To turn on strict mode, simply pass strict: true: when creating a store.

const store = new Vuex.Store({

// ...

strict: true

})

Copy the code

In strict mode, an error is thrown whenever a state change occurs that is not caused by a mutation function. This ensures that all state changes are tracked by the debugging tool.

Development environment vs. release environment

Do not enable strict mode in a release environment! Strict mode deeply monitors the status tree to detect non-compliant state changes — be sure to turn off Strict mode in a release environment to avoid performance losses.

Similar to plug-ins, we can have build tools handle this situation:

const store = new Vuex.Store({

// ...

strict: process.env.NODE_ENV ! == 'production'

})

Copy the code