[Diccionario front-end] El proceso de inyección de Vuex en el ciclo de vida de Vue

Prefacio

Este artículo es el decimotercer artículo de la serie de artículos [Front-end Dictionary]. Me centraré en Vue en los próximos 9 artículos. Espero que estos 9 artículos puedan profundizar su comprensión de Vue. Por supuesto, la premisa de estos artículos es que tienes una cierta base de Vue por defecto. Si no tiene los conceptos básicos, se recomienda leer primero la documentación oficial.

En el primer artículo, combinaré parte del código fuente de Vue y Vuex para ilustrar el proceso de inyección de Vuex en el ciclo de vida de Vue.

Cuando se trata de código fuente, no es tan difícil como podría pensar. Es casi lo mismo que solemos escribir código comercial, todas son llamadas a métodos. Pero el árbol de llamadas del código fuente será mucho más complicado.

Por que usar Vuex

Con Vue, inevitablemente encontraremos datos o estados compartidos entre componentes. El código comercial de la aplicación se vuelve cada vez más complicado y las desventajas de los métodos de comunicación, como accesorios, eventos y buses de eventos, serán más obvias. En este momento necesitamos Vuex. Vuex es una herramienta de gestión de estado especialmente diseñada para Vue.

La gestión del estado es un medio importante para desacoplar los componentes de Vue.

Se basa en las ideas básicas de Flux y redux, extrae el estado al mundo entero y forma una tienda.

[Diccionario front-end] El proceso de inyección de Vuex en el ciclo de vida de Vue

Vuex no limita la estructura de su código, pero debe seguir algunas reglas:

  1. El estado de la aplicación debe concentrarse en un solo objeto de tienda

  2. Enviar una mutación es la única forma de cambiar el estado, y este proceso es sincrónico

  3. La lógica asincrónica debe encapsularse en acción

El proceso de inyectar Vuex en el ciclo de vida de Vue

Cuando instalamos el complemento, siempre usamos Vue.use () para cargar el complemento como se muestra a continuación, pero ¿qué hace Vue.use ()?

import Vue from 'vue';

import Vuex from 'vuex';

Vue.use(Vuex);

¿Qué hace Vue.use ()

Instale el complemento Vue.js. Si el complemento es un objeto, se debe proporcionar el método de instalación. Si el complemento es una función, se utilizará como método de instalación. Cuando se llama al método de instalación, Vue se pasará como parámetro.

Lo anterior es la explicación del documento oficial.

A continuación, echemos un vistazo a lo que hace Vue.use () desde la parte del código fuente.

El código fuente de Vue llama al método initUse (Vue) en el método de entrada initGlobalAPI Este método define lo que Vue.use () necesita hacer.

function initGlobalAPI (Vue) {

  ......

  initUse(Vue);

  initMixin$1(Vue); // 下面讲 Vue.mixin 会提到

  ......

}

function initUse (Vue) {

  Vue.use = function (plugin) {

    var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));

    /* 判断过这个插件是否已经安装 */

    if (installedPlugins.indexOf(plugin) > -1) {

      return this

    }

    var args = toArray(arguments, 1);

    args.unshift(this);

    /* 判断插件是否有 install 方法 */

    if (typeof plugin.install === 'function') {

      plugin.install.apply(plugin, args);

    } else if (typeof plugin === 'function') {

      plugin.apply(null, args);

    }

    installedPlugins.push(plugin);

    return this

  };

}

Este código hace principalmente dos cosas:

  1. Uno es evitar la instalación repetida del mismo complemento

  2. El otro es inicializar el complemento.

El método de instalación del complemento

Después de leer el código fuente anterior, sabemos que el complemento (Vuex) debe proporcionar un método de instalación. Así que veamos si existe este método en el código fuente de Vuex. El resultado es, por supuesto:

/* 暴露给外部的 install 方法 */

function install (_Vue) {

  /* 避免重复安装(Vue.use 内部也会检测一次是否重复安装同一个插件)*/

  if (Vue && _Vue === Vue) {

    {

      console.error(

        '[vuex] already installed. Vue.use(Vuex) should be called only once.'

      );

    }

    return

  }

  Vue = _Vue;

  /* 将 vuexInit 混淆进 Vue 的 beforeCreate(Vue2.0) 或 _init 方法(Vue1.0) */

  applyMixin(Vue);

}

Este código hace principalmente dos cosas:

  1. Uno es evitar que Vuex se instale repetidamente

  2. La otra es ejecutar applyMixin, el propósito es ejecutar el método vuexInit para inicializar Vuex

A continuación, miramos el código fuente de applyMixin (Vue):

/* 将 vuexInit 混淆进 Vue 的 beforeCreate */

function applyMixin (Vue) {

  var version = Number(Vue.version.split('.')[0]);

  if (version >= 2) {

    Vue.mixin({ beforeCreate: vuexInit });

  } else {

    /* Vue1.0 的处理逻辑,此处省略 */

    ......

  }

  function vuexInit () {

    ......

  }

}

A partir del código fuente anterior, podemos ver que el método Vue.mixin confunde el método vuexInit con el gancho beforeCreate. Debido a esta operación, cada instancia de vm llamará al método vuexInit. Entonces, ¿qué hace vuexInit?

vuexInit ()

Cuando usamos Vuex, necesitamos pasar la tienda a la instancia de Vue.

new Vue({

  el: '#app',

  store

});

Pero podemos acceder a la tienda en cada máquina virtual, esto requiere vuexInit.

  function vuexInit () {

    const options = this.$options

    if (options.store) {

      /* 根节点存在 stroe 时 */

      this.$store = typeof options.store === 'function'

        ? options.store()

        : options.store

    } else if (options.parent && options.parent.$store) {

      /* 子组件直接从父组件中获取 $store,这样就保证了所有组件都公用了全局的同一份 store*/

      this.$store = options.parent.$store

    }

  }

Cuando el nodo raíz existe stroe, asigne directamente options.store a este. $ Store. De lo contrario, no es el nodo raíz y se obtiene del $ store del nodo principal.

Mediante este paso de operación, podemos acceder a la instancia de Store a través de este. $ Store en cualquier vm. A continuación, hablemos de Vue.mixin () al revés.

Vue.mixin ()

Registre un mixin globalmente, afectando a cada instancia de Vue creada después del registro. Los autores de complementos pueden usar mixins para inyectar comportamientos personalizados en los componentes. No recomendado para uso en código de aplicación.

El método initMixin $ 1 (Vue) se llama en el método de entrada initGlobalAPI de vue:

function initMixin$1 (Vue) {

  Vue.mixin = function (mixin) {

    this.options = mergeOptions(this.options, mixin);

    return this

  };

}

El proceso de inyección de Vuex en el ciclo de vida de Vue probablemente sea así. Si estás interesado, puedes mirar directamente el código fuente de Vuex. A continuación, hablemos de Store.

Tienda

Mencionamos anteriormente que vuexInit obtendrá Store from options. Entonces, ¿de dónde viene la tienda?

Cuando usemos Vuex, definiremos una instancia de Store similar a la siguiente.

import Vue from 'vue'

import Vuex from 'vuex'

import mutations from './mutations'

Vue.use(Vuex)

const state = {

    showState: 0,                             

}

export default new Vuex.Store({

    strict: true,

    state,

    getters,

})

No habilite el modo estricto en el entorno de publicación. El modo estricto monitoreará en profundidad el árbol de estado para detectar cambios de estado que no cumplan con las normas; asegúrese de desactivar el modo estricto en el entorno de lanzamiento para evitar la pérdida de rendimiento.

Estado receptivo

¿Te importa lo receptivo que sea el estado? Esto se logra principalmente a través del método resetStoreVM (this, state) llamado en el constructor de Store.

Este método es principalmente para restablecer un objeto _vm privado (una instancia de Vue). Este objeto _vm mantendrá nuestro árbol de estado y almacenará captadores de tienda mediante el cálculo de atributos. Ahora echemos un vistazo a su proceso de implementación.

/* 使用 Vue 内部的响应式注册 state */

function resetStoreVM (store, state, hot) {

  /* 存放之前的vm对象 */

  const oldVm = store._vm 

  store.getters = {}

  const wrappedGetters = store._wrappedGetters

  const computed = {}

  /* 通过 Object.defineProperty 方法为 store.getters 定义了 get 方法。当在组件中调用 this.$store.getters.xxx 这个方法的时候,会访问 store._vm[xxx]*/

  forEachValue(wrappedGetters, (fn, key) => {

    computed[key] = partial(fn, store)

    Object.defineProperty(store.getters, key, {

      get: () => store._vm[key],

      enumerable: true // for local getters

    })

  })

  const silent = Vue.config.silent

  /* 设置 silent 为 true 的目的是为了取消 _vm 的所有日志和警告 */

  Vue.config.silent = true

  /*  这里new了一个Vue对象,运用Vue内部的响应式实现注册state以及computed*/

  store._vm = new Vue({

    data: {

      $$state: state

    },

    computed

  })

  Vue.config.silent = silent

  /* 使能严格模式,Vuex 中对 state 的修改只能在 mutation 的回调函数里 */

  if (store.strict) {

    enableStrictMode(store)

  }

  if (oldVm) {

    /* 解除旧 vm 的 state 的引用,并销毁这个旧的 _vm 对象 */

    if (hot) {

      store._withCommit(() => {

        oldVm._data.$$state = null

      })

    }

    Vue.nextTick(() => oldVm.$destroy())

  }

}

El estado de respuesta receptivo probablemente se implemente de esta manera, que es el proceso de inicialización del método resetStoreVM.

Mira el método de confirmación de Store

Sabemos que el método de confirmación se utiliza para desencadenar la mutación.

commit (_type, _payload, _options) {

  /* unifyObjectStyle 方法校参 */

  const {

    type,

    payload,

    options

  } = unifyObjectStyle(_type, _payload, _options)

  const mutation = { type, payload }

  /* 找到相应的 mutation 方法 */

  const entry = this._mutations[type]

  if (!entry) {

    if (process.env.NODE_ENV !== 'production') {

      console.error(`[vuex] unknown mutation type: ${type}`)

    }

    return

  }

  /* 执行 mutation 中的方法 */

  this._withCommit(() => {

    entry.forEach(function commitIterator (handler) {

      handler(payload)

    })

  })

  /* 通知所有订阅者,传入当前的 mutation 对象和当前的 state */

  this._subscribers.forEach(sub => sub(mutation, this.state))

  if (

    process.env.NODE_ENV !== 'production' &&

    options && options.silent

  ) {

    console.warn(

      `[vuex] mutation type: ${type}. Silent option has been removed. ` +

      'Use the filter functionality in the vue-devtools'

    )

  }

}

Este método primero realiza la verificación del estilo de los parámetros y luego usa el método _withCommit para ejecutar esta función de procesamiento de mutación de activación por lotes. Una vez finalizada la ejecución, notifique a todos los _subscribers (función de suscripción) del objeto de mutación de esta operación y del estado actual.

Plan de salida de artículos relacionados con Vue

Recientemente, mis amigos siempre me han preguntado acerca de preguntas relacionadas con Vue, por lo que publicaré 9 artículos relacionados con Vue a continuación, con la esperanza de poder ayudarlo. Mantendré una actualización en 7 a 10 días.

  1. [Diccionario front-end] El proceso de inyección de Vuex en el ciclo de vida de Vue

  2. [Diccionario front-end] Análisis del principio de respuesta de Vue

  3. [Diccionario front-end] El proceso de parchear VNodes nuevos y antiguos

  4. [Diccionario front-end] Cómo desarrollar componentes funcionales y cargar npm

  5. [Diccionario front-end] Optimice su proyecto de Vue desde estos aspectos

  6. [Diccionario de front-end] Hable sobre el desarrollo del enrutamiento de front-end a partir del diseño de Vue-Router

  7. [Diccionario front-end] Cómo usar Webpack correctamente en el proyecto

  8. [Diccionario front-end] Procesamiento del servidor Vue

  9. [Diccionario front-end] Cómo elegir entre Axios y Fetch

Te sugiero que prestes atención a mi cuenta oficial, puedes recibir los últimos artículos lo antes posible.

[Diccionario front-end] El proceso de inyección de Vuex en el ciclo de vida de Vue

Si desea unirse a la comunicación grupal, también puede agregar mi WeChat wqhhsd.

Supongo que te gusta

Origin blog.51cto.com/15077552/2596466
Recomendado
Clasificación