Vuex profile

In the use of Vue. Js for developing large, complex applications, and data will have multiple components share the same state, or multiple components will be updated to the same state, there is less application code, we can change the data communication between components to maintain, or events, by bus for data transfer and modify. However, when the application becomes larger and larger, the code will become difficult to maintain. The multi-layer nested data transmitted through prop from the parent component will be extremely fragile due to the deep level, and the event bus will be complicated due to the increase of components and code volume, and it is difficult to clarify the transfer relationship among them.

Vuex puts the data layer into a single Store globally, making the component layer thinner and dedicated to the presentation and manipulation of data. All data changes need to go through the global Store to form a one-way data flow, making data changes “predictable”.

Vuex is designed specifically for the vuue.js framework (why? Js application state management library, it draws on the basic idea of Flux, Redux, the shared data is pulled out to the global, to a singleton storage, while using vue.js responsive mechanism for efficient state management and update. Because Vuex uses the “responsive mechanism” within vuue.js, Vuex is a framework designed specifically for vuue.js and highly compatible with it (the advantage is that it is more efficient, but the disadvantage is that it can only be used with vuue.js).

Communication mode between Vue components

The father the son (props down)

The parent component passes values to its children, and within the parent component passes values to the children by setting their properties, and within the children, passespropsProperty to accept a property passed by a child component Figure 2.type: in order toString.

Child the parent (events up)

When a child sends a value to its parent, the child sends a value to the parent by triggering an internal event or changing the state of the parent

Event sharing (event bus)

Event sharing, also known as event bus, binds different event names through an event center, and other components can start an event and change the value of the bound event

$attrs/$listeners

$attrswith$listenersThe main application is to implement multi-layer nested pass, within a parent component, through the use of child componentsv-bind/v-onBinding properties/events within a subcomponent$attrs/$listenersAccept (inpropsProperties within do not appear in$attrs), and can be nested at multiple levels

Add an inheritAttrs attribute to the Vue component. If you don’t want inheritAttrs in the component’s root element, you can set inheritAttrs: false in the component’s options. This property defaults to true, depending on the image

provide/inject

provide/injectThe main use is to pass values between components across hierarchies.provideIs defined in the parent component, and all child components are allowed to passinjectInject the variable to operate Here the variable content is inconsistent, should begrandpa.msg

ref.$parent/$children

Ref is used to register reference information for DOM elements or child components. Reference information is registered against the parent component’s $refs object. If used on ordinary DOM elements, the reference information is the element; If used on a child component, the reference information is the component instance

$childrenPoints to direct child components. Need to pay attention to$childrenIt’s not sequential, it’s not reactive. If you find yourself trying to use it$childrenFor data binding, consider using an arrayv-forTo generate child components and useArrayAs the real source. $parentPoints to the root of the current component treeVueInstance. If the current instance has no parent, the instance will be itself.

The use of Vuex

Conceptual analysis

vuexSingle state (global state) management, in the development of SPA single page components, instateOnce you have defined a piece of data, you can retrieve and modify it in any component of your project, and your changes can be synchronized globally.

It can be more vividly referred to as a warehouse for managing data, storing all the states required by multiple components (not limited to levels) in the warehouse for storage and operation. If your project status is more complex and there are more modules. Vuex also supports modules properties to help you manage these modules. Here is a vuex.store configuration parameter

  • state

    A single state tree, an object that holds state, similar to data in a component

  • getters

    fromstateIn the extension of some easy to usestate, analogous to computed in components, as explained on the official website:

    Vuex allows us to define “getters” (you can think of them as computed properties of the store) in the store. Just like evaluating properties, the return value of a getter is cached based on its dependency and is recalculated only if its dependency value changes.

  • mutations

    To change theVuexstoreThe only method of the state in. Very similar to the event, eachmutationEach has a string event typetypeAnd a callback functionhandler. This callback is where we actually make the state change, and it accepts itstateAs the first parameter.

  • actions

    Action is similar to and more powerful than mutation, but cannot modify state directly. You need to start a specific mutation to modify state, which is usually used for asynchronous operation states

  • modules

    All the state of the application is concentrated into one large object. When the application gets really complicated,storeObjects can become quite bloated. The Store can be divided into modules, each of which is like onestore

Instance methods

  • commit

    Store.mit has two arguments

    store.commit('module? /mutation', { num: 1})
    store.commit({ type: 'mutation'.num: 1 })
    Copy the code
  • Dispatch store.dispatch also has two parameters

    store.dispatch('module? /action', { num: 1})
    store.dispatch({ type: 'action'.num: 1 })
    Copy the code
  • Watch responds to the return value of a getter method and calls the callback function when the value changes.

    store.watch((state, getter) = > state.app.num,() = >{ console.log('state.app.num changed'), {}})
    Copy the code
  • RegisterModule Registers a dynamic module

    store.registerModule(moduleObject)
    Copy the code
  • HotUpdate uses WebPack’s Hot Module Replacement, and Vuex supports Hot overloading of mutation, Module, Action, and getters during development. No good examples, go to the official website of the code

    // Webpack API registers all modules
    function loadModules() {
      const context = require.context("./modules".false./([a-z_]+)\.js$/i)
    
      const modules = context
        .keys()
        .map((key) = > ({ key, name: key.match(/([a-z_]+)\.js$/i) [1] }))
        .reduce(
          (modules, { key, name }) = > ({
            ...modules,
            [name]: context(key).default
          }),
          {}
        )
    
      return { context, modules }
    }
    const { context, modules } = loadModules()
    const store = new Vuex.Store({
    	modules
    })
    
    if (module.hot) {
      // Hot reload when any module changes.
      module.hot.accept(context.id, () = > {
        const { modules } = loadModules()
    
        store.hotUpdate({
          modules
        })
      })
    }
    Copy the code
  • subscribe/subscribeAction

    Subscribe to store mutation/action. The handler is called after each mutation/action is complete, receiving the mutation/action and the status after the mutation/action as arguments.

Auxiliary function

Use of helper functions to make it easier to call methods in store. Use helper functions to make it easier to know which stores are being called in a component, instead of using store instances to run this. code.store.mit, this.$store.dispatch. One level up in the project, and later in the maintenance, you don’t know where to call the store method and change the state

  • mapState

    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 usemapStateHelper functions help us generate computed properties

  • mapGetters

    mapGetterswillstoreIn thegetterMap to local computed properties

  • mapMutations

    usemapMutationsHelper functions are added to the componentmethodsMapped tostore.commitcall

  • mapActions

    usemapActionsHelper functions are added to the componentmethodsMapped tostore.dispatchcall

Define the warehouse Using helper functions in components (example)

readingVuexThe source code

So many concepts and methods of Vuex are mentioned above. What is hidden in Vuex? Let’s look at the internal organs of Vuex (node_modules/ Vuex, version:3.4.0)

Package directory

VuexMy insides

Take a look at vuex/dist/vuex.js

  • Use (plugin) calls plugin’s install method, so we’ll start with install

    function install (_Vue) {
    if (Vue && _Vue === Vue) {
      {
        console.error(
          '[vuex] already installed. Vue.use(Vuex) should be called only once.'
        );
      }
      return
    }
    Vue = _Vue;
    applyMixin(Vue);
    }
    Copy the code

    Install calls applyMixin and passes in Vue

  • ApplyMixin method

    function applyMixin (Vue) {
      var version = Number(Vue.version.split('. ') [0]);
    
      if (version >= 2) {
        Vue.mixin({ beforeCreate: vuexInit });
      } else {
        // override init and inject vuex init procedure
        // for 1.x backwards compatibility.
        var _init = Vue.prototype._init;
        Vue.prototype._init = function (options) {
          if ( options === void 0 ) options = {};
    
          options.init = options.init
            ? [vuexInit].concat(options.init)
            : vuexInit;
          _init.call(this, options);
        };
      }
    
      /** * Vuex init hook, injected into each instances init hooks list. */
    
      function vuexInit () {
        var options = this.$options;
        // store injection
        if (options.store) {
          this.$store = typeof options.store === 'function'
            ? options.store()
            : options.store;
        } else if (options.parent && options.parent.$store) {
          this.$store = options.parent.$store; }}}Copy the code

    Call vuexInit depending on the Vue version and get options.store. If options has no store point $store to parent

  • What’s in the store

    • 370 ~ 436lineStoreConstructor function, generatedstoreobject
    • 448 ~ 631Line inStoreAdd instance methods to the prototype
    • 708 ~ 758Line of initializationmoduleThe related configuration
    • 818 ~ 890Line registrationgetters.mutations.actions.modules
    • 937 ~ 1070Line to write helper functionsmapStateEtc.
    • 1077~ 1140Line module command space operations
    • 1143~ 1196lineloggerFunction (big guy is big guy, but also remarks for referenceredux-logger, line 1141)

Implement one manuallyVuex

We follow the idea of Vuex to achieve a simple Vuex, read a bit awkward ~

writeinstallmethods

The statementstoreClass and writes the instance method

Registering a customstore

Used in components

conclusion

In September, the sky was blue, the sun hung like a fireball, and the clouds seemed to be melted by the sun and disappeared without a trace. Watching the smoke rising slowly above the houses in the distance. I shivered, swung the keyboard and continued to optimize my code

If it helps you, please don’t be stingy with your likes 👍

At the end of the article, I will send you a ticket to demo