What problem does Vuex solve?

Solve two problems

  • When multiple components depend on the same state, participation for multiple nested components can be cumbersome, and state transfer between sibling components cannot be done.
  • Behavior from different components needs to change the same state. Multiple copies of state that are referenced directly by parent components or changed and synchronized through events have been used in the past. These patterns are very fragile and often result in unmaintainable code.

When to use Vuex?

When the project encounters the following two scenarios

  • When multiple components depend on the same state.
  • Behavior from different components needs to change the same state.

How to reference Vuex?

import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const debug = process.env.NODE_ENV ! == 'production'; Const store = new vuex. store ({strict:debug, open strict mode for all non-production applications state:{}, getters:{}, mutations:{}, actions:{ } }) export default store;Copy the code

The introduction of the store

import Vue from 'vue';
import App from './App.vue';
import store from './store';
const vm = new Vue({
    store:store,
    render: h => h(App)
}).$mount('#app')
Copy the code

What are the five core attributes of Vuex?

State, getters, mutations, Actions, modules

Where is state stored in Vuex and how can it be changed?

Stored in state, the only way to change the state in Vuex is to commit mutation explicitly.

What should I pay attention to when using Vuex when the state is an object?

Because the object is a reference type, changing the property after replication will still affect the original data, which will change the state in the state, which is not allowed, so the object is copied by deep clone first and then modified.

How do I batch use Vuex state in components?

Use the mapState helper function to mix state into a computed object using the object expansion operator

import {mapState} from 'vuex' export default{ computed:{ ... mapState(['price','number']) } }Copy the code

How do I derive some state from state in Vuex and multiple components use it?

With the getter property, comparable to computed property in Vue, derived state changes only when the original state changes.

A getter takes two arguments, the first being state and the second being getters(which can be used to access other getters).

Const store = new vuex. store ({state: {price: 100, number: 5, discount: 0.6,}, getters: {total: new vuex. store ({state: {price: 100, number: 5, discount: 0.6,}, getters: {total: state => { return state.price * state.number }, discountTotal: (state, getters) => { return state.discount * getters.total } }, });Copy the code

These derived transitions can be accessed through this.$store.getters. Total in computed data for the component.

computed: {
    total() {
        return this.$store.getters.total
    },
    discountTotal() {
        return this.$store.getters.discountTotal
    }
}
Copy the code

How do you use getters to get the state of a component using specific conditions

Pass parameters to the getter by making the getter return a function. Then, the parameters are used to determine the state that meets the requirements in state.

const store = new Vuex.Store({
    state: {
        todos: [
            { id: 1, text: '...', done: true },
            { id: 2, text: '...', done: false }
        ]
    },
    getters: {
        getTodoById: (state) => (id) =>{
            return state.todos.find(todo => todo.id === id)
        }
    },
});
Copy the code

Then in the component can be used to calculate attribute computed by enclosing $store. Getters. GetTodoById (2) to access these derived in shift.

computed: {
    getTodoById() {
        return this.$store.getters.getTodoById
    },
}
mounted(){
    console.log(this.getTodoById(2).done)//false
}
Copy the code

How do I batch use Vuex’s getter property in a component

Use the mapGetters helper function to mix getters into a computed object using the object expansion operator

import {mapGetters} from 'vuex' export default{ computed:{ ... mapGetters(['total','discountTotal']) } }Copy the code

How do I alias Vuex’s getter property in bulk in a component and use it

Use the mapGetters helper function to mix getters into a computed object using the object expansion operator

import {mapGetters} from 'vuex' export default{ computed:{ ... mapGetters({ myTotal:'total', myDiscountTotal:'discountTotal', }) } }Copy the code

In the Vuex state there is a state number that indicates the number of goods and how the component changes it.

Mutations will be registered in mutations first

const store = new Vuex.Store({ state: { number: 10, }, mutations: { SET_NUMBER(state,data){ state.number=data; }}});Copy the code

Use this. codestore.mit to commit mutation in the component to change the number

this.$store.commit('SET_NUMBER',10)
Copy the code

What to look out for using mutation in Vuex.

Mutation must be a synchronization function

Commit the same mutation multiple times in the component.

Use the mapMutations helper function, and use it in the component

import { mapMutations } from 'vuex' methods:{ ... mapMutations({ setNumber:'SET_NUMBER', }) }Copy the code

Then call this.setNumber(10) equivalent to call this.codestore.com MIT (‘SET_NUMBER’,10)

If you submit the same action multiple times in a component, it’s easier to write and use it.

Use the mapMutations helper function, and use it in the component

methods:{ ... mapActions({ setNumber:'SET_NUMBER', }) }Copy the code

Then calling this.setNumber(10) is equivalent to calling this.$store.dispatch(‘SET_NUMBER’,10).

What is the difference between Action and mutation in Vuex?

Difference:

  • The action commits mutation rather than a direct state change. Mutation can change the state directly.
  • Actions can contain any asynchronous operation. Mutation can only be a synchronous operation.
  • Action is submitted using this.store. dispatch(‘ ACTIONNAME ‘,data). − Mutation is committed using this.store.dispatch(‘ACTION_NAME’,data). -mutation is committed using this.store.dispatch(‘ ACTIONNAME ‘,data). −mutation is committed using this.store.mit (‘SET_NUMBER’,10).
  • The mutation first parameter is state, and the action first parameter is context, which contains the following parameters
{state, // equivalent to 'store.state' or local state rootState in modules, // equivalent to 'store.state', Commit, // equivalent to 'store.mit' dispatch, // equivalent to 'store.dispatch' getters, // Equivalent to 'store.getters' rootGetters // Equivalent to' store.getters', only exists in modules}Copy the code

Similarities:

  • Both of the second parameters can receive arguments passed in from external submissions.
this.$store.dispatch('ACTION_NAME',data)
this.$store.commit('SET_NUMBER',10)
Copy the code

Actions in Vuex are usually asynchronous, so how do you know when an action ends?

Return the Promise in the action function, and then handle the submission

actions:{
    SET_NUMBER_A({commit},data){
        return new Promise((resolve,reject) =>{
            setTimeout(() =>{
                commit('SET_NUMBER',10);
                resolve();
            },2000)
        })
    }
}
this.$store.dispatch('SET_NUMBER_A').then(() => {
  // ...
})
Copy the code

Vuex has two actions, actionA and actionB, both of which are asynchronous operations. ActionA needs to be submitted in actionB, and other operations need to be processed after actionA processing. How to implement this?

Use ES6 async and await to implement.

actions:{ async actionA({commit}){ //... }, async actionB({dispatch}){await dispatch ('actionA')// Wait for actionA to complete //... }}Copy the code

Have you used Vuex module? Why and how?

Yes, because with a single state tree, all the states of the application are grouped into one large object. When the application becomes very complex, the Store object can become quite bloated. So store is divided into modules. Each module has its own state, mutations, actions, getters, and even nested submodules, which are divided in the same way from top to bottom. Create moduleA.js and moduleb. js files in the module file. Write to the file

const state={
    //...
}
const getters={
    //...
}
const mutations={
    //...
}
const actions={
    //...
}
export default{
    state,
    getters,
    mutations,
    actions
}
Copy the code

Then index.js will introduce the module

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import moduleA from './module/moduleA'
import moduleB from './module/moduleB'
const store = new Vuex.Store({
    modules:{
        moduleA,
        moduleB
    }
})
export default store
Copy the code

Is state, the first argument received by the getter and mutation in the module, global or modular?

The first parameter state is the module’s state, that is, local state.

In the module, getters, mutation, action, how to access the global state and getter?

  • Getter: You can access the global state with the third parameter rootState and the global getter with the fourth parameter rootGetters.
  • Mutation: no global satAT and getters are accessed, and only local states are accessed.
  • Action: In the first argument context, context.rootState accesses the global state, and context.rootGetters accesses the global getter.

How do I access the getters and state in the Vuex module, and how do I submit mutation and action?

  • Getters and this.store. Getters and this.store. Getters and this.store.
  • Submit mutations in the module directly via this. codestore.mit (‘mutationA’,data).
  • Submit the actions in the module directly via this.$store.dispatch(‘actionA,data’).

Have you used the Vuex module namespace? Why and how?

By default, action, mutation, and getters in modules are registered in the global namespace. Mutations, actions with the same name in all modules will be triggered.

That’s a lot of coupling, and if you want to make your modules more encapsulation and reusable, you can make them namespaced by adding Namespaced: True.

export default{
    namespaced: true,
    state,
    getters,
    mutations,
    actions
}
Copy the code

How do I submit global mutation and action in a module with namespaces?

Pass {root: true} as the third argument to Dispatch or commit.

this.$store.dispatch('actionA', null, { root: true })
this.$store.commit('mutationA', null, { root: true })
Copy the code

How to register global actions in namespaced modules?

Add the root: true

actions: { actionA: { root: true, handler (context, data) { ... }}}Copy the code

How do components submit mutationA in moduleA with a namespace in Modules?

this.$store.commit('moduleA/mutationA',data)
Copy the code

How do I use the mapState, mapGetters, mapActions, and mapMutations functions to bind a module with a namespace?

First use createNamespacedHelpers to create helper functions based on a namespace

import { createNamespacedHelpers } from 'vuex'; const { mapState, mapActions } = createNamespacedHelpers('moduleA'); Export Default {computed: {// Find in 'module/moduleA'... MapState ({a: state => state.a, b: state => state.b})}, methods: {// Find in 'module/moduleA'... mapActions([ 'actionA', 'actionB' ]) } }Copy the code

Has the Vuex plugin ever been useful? How to use a brief introduction?

The UEX plug-in is a function that takes store as its only argument. Plugins are introduced in the vuex.store constructor option. Write in the store/plugin.js file

export default function createPlugin(param){ return store =>{ //... }}Copy the code

Then write to the store/index.js file

import createPlugin from './plugin.js'
const myPlugin = createPlugin()
const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})
Copy the code

How do I listen for mutation and action submissions in a component in a Vuex plug-in?

Subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe

export default function createPlugin(param) { return store => { store.subscribe((mutation, State) => {console.log(mutation. Type)// is that mutation console.log(mutation. Payload) console.log(state)}) // store.subscribeAction((action, State) => {// console.log(action.type)// is that action // console.log(action.payload)// submit the parameters of the action //}) Store. SubscribeAction ({before: (action, state) => {console.log(' before Action ${action.type} ')}, after: (Action, state) => {console.log(' after action ${action.type} ')}})}}Copy the code

Then write to the store/index.js file

import createPlugin from './plugin.js'
const myPlugin = createPlugin()
const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})
Copy the code

How to use the value of state in Vuex on v-Model?

You need to convert it using computed attributes.

<input v-model="message">
// ...
computed: {
    message: {
        get () {
            return this.$store.state.message
        },
        set (value) {
            this.$store.commit('updateMessage', value)
        }
    }
}
Copy the code

What is the strict mode of Vuex, what does it do, and how to open it?

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.

In the vuex.store constructor option, as shown below

const store = new Vuex.Store({
    strict:true,
})
Copy the code