directory

  • Review of communication between Vue components
    • State management processes within components
    • Communication between components
      • Parent component passing value to child component (simplest way)
      • Child components pass values to parent components
      • Values are passed between unrelated components
      • Other common methods ($ref)
  • Simple state management solution
    • The problem with communication between components above
    • Centralized state management solution
  • Vuex
    • What is a Vuex?
    • When is Vuex used?
      • Do not use Vuex unless necessary
      • Medium and large single-page applications are better to use
    • Review of Vuex core concepts
    • Vuex basic structure
    • The use of State
    • The use of Getter
    • The use of Mutation
      • The adjustment of the Mutation
        • Time travel
        • State the rollback
        • Submit the change
    • The Actions of the use of
    • The use of Modules
      • The module definition
      • Module registration
      • Module USES
      • Adding a namespace
    • Vuex strict mode
    • Vuex plug-in
      • Use of plug-ins

The last day of the end of the year did not intend to blog, but left the impression that I am still studying hard this year haha. This is my first blog about VUE. It’s not too late. First to the content of this blog for a comb, interested partners can jump to their interest in the place, this blog is quite long, long warning.

Review of communication between Vue components

State management processes within components

The two core functions of Vue are data-driven and componentization

Using component-based development can increase development efficiency and lead to better maintainability.

new Vue({
    // state Components can manage their own internal state internally
    data () {
        return {
            count: 0}},// View view. Each component has its own view that binds state to the view. The state may change when the user interacts with the view
    template: `<div>{{ count }}</div>`.// Actions, which describes state management within a single component. In practice, multiple components may share state
    methods: {
        increment () {
            this.count++
        }
    }
})
Copy the code

State management is the solution to the problem of multiple components sharing state through state, centralized management and distribution.

  • state: state, data source.
  • view: the view. Present the state to the user by binding it to the view
  • actions: How the user interacts with the view to change state

As shown in the figure, the state is bound to the view and presented to the user. The user changes the state by interacting with the view. The changed state is then bound to the view and presented to the user. A one-way data flow is simple and clean, but sharing data between multiple components can break this simple structure.

Review of communication between components

In most cases, components do not exist in isolation; they need to work together to form a complex business function. In Vue, different communication rules are provided for different component relationships.

Common communication modes between components are:

Parent component passing value to child component (simplest way)

  • A parent component passes a value to a child component via the corresponding property
  • Child component passpropsReceive data
<! -- Subcomponent -->
<template>
  <div>
    <h1>Props Down Child</h1>
    <h2>{{ title }}</h2>
  </div>
</template>

<script>
export default {
  // The child component uses props to receive values passed by the parent component
  // props can be arrays or objects
  // If you want to specify the type of the value to be passed, the title is set to string. If you want to pass number, an error is reported
  // props: ['title'],
  props: {
    title: String}}</script>

<style>

</style>
Copy the code
<! -- Parent component -->
<template>
  <div>
    <h1>Props Down Parent</h1>
    <! Pass a value to a child component via a property, or in this case an expression, and bind a member of data -->
    <child title="My journey with Vue"></child>
  </div>
</template>

<script>
import child from './01-Child'
export default {
 // 1. Register child components
  components: {
    child
  }
}
</script>

<style>

</style>
Copy the code

Child components pass values to parent components

  • The child component uses custom events$emitWhen triggered, it takes parameters and passes values to the parent component
  • The parent component passes$onRegisters events that are triggered within a child component and receives data that is passed within the line$eventGets the parameters passed by the event (not used in event handlers)
<! -- Subcomponent -->
<template>
  <div>
    <h1 :style="{ fontSize: fontSize + 'em' }">Props Down Child</h1>
    <button @click="handler">Text increase</button>
  </div>
</template>

<script>
export default {
 // Accept the default font size passed by the parent component via props
  props: {
    fontSize: Number
  },
  methods: {
    handler () {
    // When you click the button, trigger the custom event enlargeText enlarge font, make font enlarge 0.1
    // This.$emit this is a custom event that is emitted by the sub-component and registered for the sub-component when the event is registered
      this.$emit('enlargeText'.0.1)}}}</script>

<style></style>
Copy the code
<! -- Parent component -->
<template>
  <div>
  <! -- The parent component will bind fontSize -->
    <h1 :style="{ fontSize: hFontSize + 'em'}">Event Up Parent</h1>The text here doesn't need to change<! EnlargeText; enlargeText; enlargeText;
    <child :fontSize="hFontSize" v-on:enlargeText="enlargeText"></child>
    <child :fontSize="hFontSize" v-on:enlargeText="enlargeText"></child>
    <! $event = 0; $event = 0; $event = 0;
    <child :fontSize="hFontSize" v-on:enlargeText="hFontSize += $event"></child>
  </div>
</template>

<script>
import child from './02-Child'
export default {
  components: {
    child
  },
  data () {
    return {
      hFontSize: 1}},methods: {
  // The child passes the value to the parent, which receives the value as an argument and performs the calculation
    enlargeText (size) {
      this.hFontSize += size
    }
  }
}
</script>

<style></style>
Copy the code

Values are passed between unrelated components

  • Custom events are also used, but because there is no parent-child relationship, the value cannot be triggered by a child component, so it is used hereeventBusThat is, create a publicVueInstance, which acts as an event bus, or event hub.
  • eventBus: Create aVueExample, this instance is not used to display content, so no options are passed, we use it for the purpose of using$emitand$onTo trigger and register events.
  • Trigger event component: Pass$emitFires the event and passes parameters
  • Register event components: Pass$onRegisters the event and receives the parameters for processing
// eventbus.js
import Vue from 'vue'
export default new Vue()
Copy the code
<! -- Component 1: Trigger event -->
<template>
  <div>
    <h1>Event Bus Sibling01</h1>
    <div class="number" @click="sub">-</div>
    <input type="text" style="width: 30px; text-align: center" :value="value">
    <div class="number" @click="add">+</div>
  </div>
</template>

<script>
// This component fires the event to import the event center
import bus from './eventbus'

export default {
// props parameter num
  props: {
    num: Number
  },
  // Because the value of props cannot be changed arbitrarily, pass it to value
  created () {
    this.value = this.num
  },
  data () {
    return {
      value: -1}},methods: {
  // The value cannot be 0
    sub () {
      if (this.value > 1) {
        this.value--
        // Trigger the bus custom event numchange and pass value as an argument
        bus.$emit('numchange'.this.value)
      }
    },
    // Add operation, similar to subtract
    add () {
      this.value++
      bus.$emit('numchange'.this.value)
    }
  }
}
</script>

<style>
.number {
  display: inline-block;
  cursor: pointer;
  width: 20px;
  text-align: center;
}
</style>
Copy the code
<! -- Component 2: Definitions -->
<template>
  <div>
    <h1>Event Bus Sibling02</h1>

    <div>{{ msg }}</div>
  </div>
</template>

<script>
// Import the event center because you want to register events
import bus from './eventbus'
export default {
  data () {
    return {
      msg: ' '
    }
  },
  created () {
    // Numchange events are registered through the bus. The event handler receives the parameters passed when the event is triggered
    bus.$on('numchange'.(value) = > {
      this.msg = 'You have chosen${value}Goods `}}})</script>

<style>

</style>
Copy the code
<! --App.vue-->
<template>
  <div id="app">
    <h1>Unrelated components pass values</h1>
    <sibling0301 :num="num"></sibling0301>
    <sibling0302></sibling0302>
  </div>
</template>

<script>
import sibling0301 from './components/03-event-bus/03-Sibling-01'
import sibling0302 from './components/03-event-bus/03-Sibling-02'

export default {
  name: 'App'.components: {
    sibling0301,
    sibling0302,
  },
  data () {
    return {
      num: 1}}}</script>

<style></style>
Copy the code

Other common ways

  • $root.$parent.$children.$refAnd obtain the root component member through these attributes to realize the communication between components.But these are not recommended. This is only used if the project is small or if you are developing custom components. For large projects, it is recommended to use Vuex to manage state.

The following example uses $refs to get the state of a child component, while other properties can view the documentation for themselves.

refTwo functions of

  1. In the ordinaryHTMLUse on labelsrefwith$refsWhat we get is thetaDOMobject
  2. Use on component labelsrefwith$refsYou get the component instance
<! Subcomponent, a simple custom component with a custom text box that can get focus. -->
<template>
  <div>
    <h1>ref Child</h1>
    <! The ref attribute is set on the input tag.
    <input ref="input" type="text" v-model="value">
  </div>
</template>

<script>
export default {
  data () {
    return {
      value: ' '}},methods: {
    focus () {
      // Call this.$refs.input to get the DOM object of the input and call its focus method to get the focus of the textbox
      this.$refs.input.focus()
    }
  }
}
</script>

<style></style>
Copy the code
<! -- Parent component, -->
<template>
  <div>
    <h1>ref Parent</h1>
    <! -- Set ref--> on the label of the child component
    <child ref="c"></child>
  </div>
</template>

<script>
import child from './04-Child'
export default {
  components: {
    child
  },
  mounted () {
    // In the mounted function, you need to wait for the component to finish rendering
    // This.$refs.c is the child component object, which can access its properties and methods
    // Call the subcomponent method to get focus internally
    this.$refs.c.focus()
    // Assign a value to the text box via the value attribute
    this.$refs.c.value = 'hello input'}}</script>

<style>

</style>
Copy the code

Again, this is not recommended, as it can cause confusion in state management if abused.

Simple state management solution

The problem with communication between components above

If multiple components need to share state, using the previously demonstrated method can be achieved, but it is cumbersome, and multiple components transfer values, it is difficult to track data changes. If there is a problem, it is difficult to locate the problem. When multiple components need to share state, typical scenarios such as shopping carts are not suitable for us to use the scheme described before, and the following problems may be encountered:

  • Multiple views depend on the same state. If multiple nested components depend on the same state, using parent-child component pass-throughs is possible, but cumbersome and difficult to manage.
  • Behavior from different views requires changing the same state, which can be modified by parent-child components, or by event mechanisms, or by synchronizing state changes, which are very fragile and often result in unmaintainable code.

Centralized state management solution

To solve these problems, we extract the shared state of different components, store it in a global object and ensure that it is responsive for future use. After the object is created, there is a global state and a method to modify the state. Any of our components can obtain and modify the state in the global object by calling the method in the object (components are not allowed to modify the state property of the object directly).

The state of multiple components can be stored in a central place and changes can be detected. Instead of using Vuex, we will do a simple implementation ourselves.

  1. Create a globalstore.js

Centralized state management, where all the states are. This module exports an object that is a state repository and globally unique object that can be imported by any component

There’s the state, there’s the Actions, and the state is for storing the state, and the actions are for the user to interact to change the view. There is also a Debug attribute for easy development and debugging.

// store.js
export default {
  debug: true.state: {
    user: {
      name: 'xiaomao'.age: 18.sex: 'male'
    }
  },
  setUserNameAction (name) {
    if (this.debug) {
      console.log(' 'setUserNameAction triggered., name)
    }
    this.state.user.name = name
  }
}
Copy the code
  1. Import in the component
<! Components - A - - >
<template>
  <div>
    <h1>componentA</h1>
    <! --3. You can display data directly in a view as a dot -->
    user name: {{ sharedState.user.name }}
    <button @click="change">Change Info</button>
  </div>
</template>

<script>
// 1. Import store into the component
import store from './store'
export default {
  methods: {
    // 4. When the button is clicked, call the store method and change the value to componentA
    change () {
      store.setUserNameAction('componentA')
    }
  },
  data () {
    return {
      // the current component can also have its own privateState, stored in privateState
      privateState: {},
      // 2. Assign the store state property to shareState
      sharedState: store.state
    }
  }
}
</script>

<style></style>
Copy the code
<! ComponentB = componentB; componentB = componentB;
<template>
  <div>
    <h1>componentB</h1>
    user name: {{ sharedState.user.name }}
    <button @click="change">Change Info</button>
  </div>
</template>

<script>
import store from './store'
export default {
  methods: {
    change () {
      // componentB (componentB
      store.setUserNameAction('componentB')
    }
  },
  data () {
    return {
      privateState: {},
      sharedState: store.state
    }
  }
}
</script>

<style></style>
Copy the code

Both components A and B share global state, and users can change state. During debugging, press the button for componentA and both become componentA, and press the button for componentB and both become componentB.

We do not change the value of the state directly in the component. Instead, we change the value by calling the Store’s actions. The advantage of this logging is that it is possible to record all state changes in the store, and when it is possible to record state changes in the store, advanced debugging functions can be implemented. Examples: timeTravel and history rollback.

The store I just used is actually a Vuex repository.

When a project is complex and multiple components share state, using inter-component communication is cumbersome and requires maintenance. At this point we can use a centralized state solution called Vuex

Vuex

Okay, finally, here we go

What is a Vuex?

  • Vuex website
  • VuexIs specially designed forVue.jsDesign of state management library, from the point of view of use is actually aJavaScriptlibrary
  • It uses a centralized way to store the data that needs to be shared, if there are too many states it is difficult to manage, soVuexIt also provides a modular mechanism to manage different states by module
  • Its role is to carry out state management, solve complex component communication, data sharing
  • VuexAlso integrated into theVueThe official debugging tooldevtools extensionTo provide thetime-travelAdvanced debugging functions such as time travel, history rollback, status snapshot, import and export

When is Vuex used?

Do not use Vuex unless necessary

Vuex can help us manage the shared state between components, but to use Vuex in a project, we need to understand the new concepts and some apis brought by Vuex. If the project is not large and there is not much shared state between components, the benefits of using Vuex are not as great as the time invested. At this point, a simple store model or some other means would suffice.

Medium and large single-page applications are better to use

In medium to large single-page applications, using Vuex can help us solve the problem where multiple views depend on the same state and behavior from different views needs to change the same state. For businesses that meet these conditions, using Vuex for state management will give us a better handle on the state of the components and bring better returns. A typical example: shopping carts.

Note: Don’t abuse Vuex as it will complicate the business.

Review of Vuex core concepts

The following diagram shows the core concepts of Vuex and shows the entire workflow of Vuex

  • Store: warehouse,StoreIs the use ofVuexThe core of an application, only one per applicationStoreIt is a container that contains most of the state in the application, but we cannot change it directlyStoreThe state in which we want to submitMutationsThe way to change the state.
  • State: state, saved inStorebecauseStoreIt’s unique, soStateIt’s also unique, it’s called a single state tree, where the states are reactive.
  • Getter: the equivalent ofVuexIt is convenient to derive other values from an attribute. It can cache the computed results internally and recalculate only when the state of the dependency changes.
  • Mutation: State changes must be committedMutationTo complete.
  • ActionsAnd:MutationSimilarly, the difference is that it can be done asynchronously, and all internal state changes need to be changedMutation.
  • Module: module, because the use of a single state tree so that all the states into a relatively large object, when the application becomes very complex,StoreObjects become quite bloated in order to solve these problemsVuexAllow us to bringStoreDivided into modules, each module has its ownState.Mutation.Actions.GetterOr even nested submodules.

Vuex basic structure

When creating a project using VUE-CLI, if Vuex is selected, the basic structure of Vuex is automatically generated.

// store.js
import Vue from 'vue'
// Import Vuex
import Vuex from 'vuex'
// Register the plug-in with the use method
// The plugin internally injects the Vuex Store into the Vue instance
Vue.use(Vuex)
// Create a Vuex Store object and export it
export default new Vuex.Store({
    state: {... },mutations: {... },actions: {... },modules: {... }// Getters are available if needed
})
Copy the code
//App.js
// Import the store object
import store from './store'
new Vue({
    router,
    // When initializing a Vue, pass in the Store option, which will be injected into the Vue instance
    This is where we inject the this.$store we use in the component
    store,
    render: h= > h(App)
}).$mount('#app')
Copy the code

The use of State

  1. Download the project templatevuex-sample-temp ,npm installDownload dependencies instore/index.jsDefine twostate
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0.msg: 'hello vue'
  },
  mutations: {},actions: {},modules: {}})Copy the code
  1. inApp.vueThe use ofstateAnd then usenpm run serveView the results
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    count: {{ $store.state.count}} <br/>
    msg: {{ $store.state.ms }}
  </div>
</template>
<script>
Copy the code
  1. Every time you use a variable, write it first$store.state is cumbersome, so Vuex is used insteadInternally suppliedmyStateFunction, which will help us generate the computed properties corresponding to the state
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    <! Count (' count ', 'MSG');
    count: {{ count }} <br/>
    msg: {{ msg }}
  </div>
</template>
<script>
  // 1. Introduce the mapState module of vuex
  import { mapState } from 'vuex'
  export default {
    // 2. Call the mapState function in the calculated properties
    computed: {
      // 3. MapState needs to receive an array as an argument. The elements of the array are state attributes to be mapped
      // Returns an object containing two methods for evaluating properties
      // { count: state => state.count, msg: state => state.msg }
      // Then we use the extension operator to expand the object, and when we're done we have count and MSG. mapState(['count'.'msg'])}}</script>
Copy the code
  1. The above method is relatively neat but if the component itself has onecountormsgProperty, causing a name conflict and requiring an alias.
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    <! If you want to use an alias, you can use it.
    count: {{ num }} <br/>
    msg: {{ message }}
  </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  computed: {
    // mapState can pass objects, keys are aliases, and values are mapping state attributes. mapState({num: 'count'.message: 'msg'}}})</script>
Copy the code

The use of Getter

Getters in Vuex are equivalent to computed properties in a component. If you want to perform simple manipulation of state data in the presentation, you can use getters

Vuex getters are used instead of computed properties in components because the state itself belongs to Vuex and should be handled internally

  1. instore.jsSet in thegetters
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0.msg: 'hello vue'
  },
  // Use the same method as calculating attributes
  getters: {
    reverseMsg (state) {
      return state.msg.split(' ').reverse().join(' ')}},mutations: {},actions: {},modules: {}})Copy the code
  1. inApp.vueThe use of
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    <h2>reverseMsg: {{ $store.getters.reverseMsg }}</h2>
    <br/>
  </div>
</template>
Copy the code
  1. Again, that’s too much trouble to quote, so andmapStateAgain, use internalmapGetters, is also the computed property that maps it to the component, its usage andmapStateYou can also set aliases using objects to avoid collisions.
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    <h2>reverseMsg: {{ reverseMsg }}</h2>
    <br/>
  </div>
</template>
<script>
// 1. Introduce the vuex mapGetters module
import { mapGetters } from 'vuex'
export default {
  // 2. Call the mapGetters function in the calculated properties
  computed: {
    // 3. Use the same as mapState, where you can also use object alias. mapGetters(['reverseMsg'])}}</script>
Copy the code

The use of Mutation

State changes must be submitted for Mutation, which must be performed synchronously.

  1. When the user clicks the button,countThe value is increased first instore.jsIn the writingMutationfunction
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0.msg: 'hello vue'
  },
  mutations: {
    // Add a function that takes two arguments
    // The first state
    // The second is payload. Payload is an extra parameter submitted on mutations. It can be an object, but it's a number
    increate (state, payload) {
      state.count += payload
    }
  },
  actions: {},modules: {}})Copy the code
  1. inApp.vueSet the button and register the event
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    count: {{ $store.state.count }} <br/>
    <h2>Mutation</h2>
    <! The first parameter is the name of the called method, and the second parameter is the payload.
    <button @click="$store.commit('increate', 2)">Mutation</button>
  </div>
</template>
Copy the code
  1. When I click the button,countThe value of each+ 2
  2. The following writing method optimization, usingmapMethod will be the currentmutationMap tomethodsIn, it still returns an object that storesmutationThe method of mapping
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    count: {{ $store.state.count }} <br/>
    <h2>Mutation</h2>
    <! Select * from 'state'; select * from 'state'; select * from 'state';
    <button @click="increate(3)">Mutation</button>
  </div>
</template>
<script>
// 1. Introduce the mapMutations module of VUex
import { mapMutations } from 'vuex'
export default {
  // 2. methods call mapMutations method
  methods: {
    ...mapMutations(['increate'])}}</script>
Copy the code

The adjustment of the Mutation

When you get to 4, at this point look at DevTools and look at time travel and history rollback, and here’s the initial state

A click of the button adds a record and shows the changed data

If the data is incorrect, you can debug it.

Time travel

And then a little more time travel.

After clicking the button, the state changes to the previous state, which is also used for debugging purposes

State the rollback

This icon is state rollback

When clicked, the code returns to the state where this step was not performed

Submit the change

The button below means to make this submission the last

When you click, base State changes to that State, and the rest of the states start from that State

The Actions of the use of

If there are asynchronous changes, you need to use Actions, in which asynchronous actions can be performed, and when the asynchronous operation is over, you also need to commit Mutation if you need to change the state.

  1. inactionsAdd method toincreateAsync
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0.msg: 'hello vue'
  },
  mutations: {
    increate (state, payload) {
      state.count += payload
    }
  },
  actions: {
    // Actions methods take two parameters: the first parameter is the context, which has members such as state, commit, and getters, and the second parameter is payLoad
    increateAsync (context, payLoad) {
      setTimeout(() = > {
        context.commit('increate', payLoad)
      }, 2000)}},modules: {}})Copy the code
  1. inApp.vueThe use ofdispatch.actionsAll the way to use this
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    count: {{ $store.state.count }} <br/>
    <h2>Actions</h2>
    <! -- use dispatch-->
    <button @click="$store.dispatch('increateAsync',5)">Action</button>
  </div>
</template>
Copy the code
  1. I’m going to optimize, and this is the time to introducemapActions
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    count: {{ $store.state.count }} <br/>
    <h2>Actions</h2>
    <button @click="increateAsync(5)">Action</button>
  </div>
</template>
<script>
// 1. Introduce the mapActions module of vuex
import { mapActions } from 'vuex'
export default {
  methods: {
    // This is a mapping to the Actions method that maps this.increateAsync to this.$store.dispatch. mapActions(['increateAsync'])}}</script>
Copy the code

The use of Modules

Modules allow us to split a single state tree into modules, each of which can have its own state, mutation, action, getter, and even nested submodules.

The module definition

In the Store folder, create a Modules folder, where each JS file is a module. Here’s how each module is defined

const state = {
  products: [{id: 1.title: 'iPhone 11'.price: 8000 },
    { id: 2.title: 'iPhone 12'.price: 10000}}]const getters = {}
const mutations = {
  setProducts (state, payload) {
    state.products = payload
  }
}
const actions = {}

export default {
  namespaced: false,
  state,
  getters,
  mutations,
  actions
}

Copy the code

Module registration

  1. Enter this module first
import products from './modules/products'
import cart from './modules/cart'
Copy the code
  1. Later, inmodulesAfter registering, this will mount the module tostorethestateMedium, and here you can passstore.state.productsAccess to theproductsA member of a module, and also a member of a modulemutationThe members recordedstoreInternal properties of_mutationMedium, yescommitDirectly submitmutation.
export default new Vuex.Store({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {
    products,
    cart
  }
})
Copy the code

Module USES

  1. inApp.vueThe use of,stateI just point it out,mutationOr usecommitmethods
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    <h2>Modules</h2>
    <! The first product is the products module, and the second product is the products attribute of the state of the module.
    products: {{ $store.state.products.products }} <br/>
    <button @click="store.commit('setProducts',[])">Mutation</button>
  </div>
</template>
Copy the code

Adding a namespace

Since mutation can be the same name in each module, the use of namespaces is recommended for easy management.

  1. Added in the export section of the module when the namespace is enablednamespaced
const state = {}
const getters = {}
const mutations = {}
const actions = {}

export default {
  // True means on, false or no means off
  namespaced: false,
  state,
  getters,
  mutations,
  actions
}

Copy the code
  1. When usedApp.vueTo set up instateIs from the module, if there is no namespace, is globalstate.
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    products: {{ products }} <br/>
    <button @click="setProducts([])">Mutation</button>
  </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
  computed: {
    // In the module state, the first argument writes the module name, and the second argument writes the array or object. mapState('products'['products'])},methods: {
    Mutations in the module, the first one writes the module name, and the second one writes the array or object. mapMutations('products'['setProducts'])}}</script>
Copy the code

Vuex strict mode

All state changes must be submitted for mutation. However, if $store.state. MSG is obtained from the component for modification, there is no problem at the syntax level, but the Vuex convention is broken, and devTools cannot track the state change. Complains.

  1. inindex.jsInitialization,StoreTurn on strict mode
export default new Vuex.Store({
  strict: true.state: {... },... }Copy the code
  1. inApp.vueStatement that uses a direct assignment in
<template>
  <div id="app">
    <h1>Vuex - Demo</h1>
    <h2>strict</h2>
    <button @click="$store.state.msg = 'hello world~'">strict</button>
  </div>
</template>
Copy the code
  1. Clicking the button changes the content, but the console throws an error

Note: Do not enable strict mode in a production environment, as strict mode will deeply examine the state tree and affect performance. Turn strict mode on in development mode and turn strict mode off in production

export default new Vuex.Store({
 strict: process.env.NODE_ENV ! = ='production'.state: {... }Copy the code

Vuex plug-in

  • VuexA plug-in is a function that accepts onestoreThe parameters of the
  • In this function, you can register functions in allmutationsExecute after completion

Use of plug-ins

  • The plug-in should be createdStoreBefore I create
  • subscribefunction
    • The purpose is to subscribestoreIn themutation
    • His callback function will be in eachmutationAfter the call
    • subscribeIt takes two arguments, the first ismutation, can also distinguish the module’s namespace. The second argument isstateInside is the stored state
  1. Define the plugin
// This function takes the store argument
const myPlugin = store= > {
    // called when store is initialized
    store.subscribe((mutation, state) = > {
        // called after each mutation
        The format of // mutation is {type, payload}
        // Type is "module name /state attribute"
        // State is in the format {module 1, module 2}})}Copy the code
  1. inStoreRegistered plug-ins in
const store = new Vuex.Store({
    / /...
    plugins: [myPlugin]
})
Copy the code