[Dicionário de front-end] O processo de injeção do Vuex no ciclo de vida do Vue

Prefácio

Este é o 13º artigo da série de artigos [Dicionário de front-end]. Vou me concentrar no Vue nos próximos 9 artigos. Espero que esses 9 artigos possam aprofundar seu conhecimento sobre o Vue. Claro, a premissa desses artigos é que você tem uma certa base do Vue por padrão. Se você não tem nenhum básico, é recomendável ler a documentação oficial primeiro.

No primeiro artigo, combinarei parte do código-fonte do Vue e do Vuex para ilustrar o processo de injeção do Vuex no ciclo de vida do Vue.

Quando se trata de código-fonte, não é tão difícil quanto você pode imaginar. É quase o mesmo que normalmente escrevemos código de negócios, são todas chamadas de método. Mas a árvore de chamadas do código-fonte será muito mais complicada.

Por que usar Vuex

Com o Vue, inevitavelmente encontraremos dados ou estados compartilhados entre os componentes. O código de negócios do aplicativo se torna cada vez mais complicado e as desvantagens dos métodos de comunicação, como adereços, eventos e barramentos de eventos, tornam-se mais óbvias. Neste momento, precisamos do Vuex. Vuex é uma ferramenta de gerenciamento de estado especialmente projetada para Vue.

A gestão do estado é um meio importante de dissociar os componentes do Vue.

Baseia-se nas ideias básicas de Fluxo e redux, extrai o estado para o mundo inteiro e forma uma loja.

[Dicionário de front-end] O processo de injeção do Vuex no ciclo de vida do Vue

Vuex não limita sua estrutura de código, mas você precisa seguir algumas regras:

  1. O estado no nível do aplicativo deve ser concentrado em um único objeto de armazenamento

  2. Enviar uma mutação é a única maneira de alterar o estado, e este processo é síncrono

  3. A lógica assíncrona deve ser encapsulada em ação

O processo de injeção de Vuex no ciclo de vida Vue

Quando instalamos o plugin, sempre usamos Vue.use () para carregar o plugin como o seguinte, mas o que Vue.use () faz?

import Vue from 'vue';

import Vuex from 'vuex';

Vue.use(Vuex);

O que Vue.use () faz

Instale o plugin Vue.js. Se o plug-in for um objeto, o método de instalação deve ser fornecido. Se o plugin for uma função, ele será usado como método de instalação. Quando o método de instalação é chamado, o Vue será passado como um parâmetro.

O acima é a explicação do documento oficial.

A seguir, vamos dar uma olhada no que Vue.use () faz a partir da parte do código-fonte.

O código-fonte do Vue chama o método initUse (Vue) no método de entrada initGlobalAPI, este método define o que Vue.use () precisa fazer.

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 faz principalmente duas coisas:

  1. Um é evitar a instalação repetida do mesmo plugin

  2. A outra é inicializar o plugin

O método de instalação do plugin

Depois de ler o código-fonte acima, sabemos que o plug-in (Vuex) precisa fornecer um método de instalação. Então, vamos ver se existe esse método no código-fonte do Vuex. O resultado é claro:

/* 暴露给外部的 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 faz principalmente duas coisas:

  1. Uma é evitar que o Vuex seja instalado repetidamente

  2. A outra é executar o applyMixin, o objetivo é executar o método vuexInit para inicializar o Vuex

A seguir, examinamos o código-fonte do 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 do código-fonte acima, podemos ver que o método Vue.mixin confunde o método vuexInit com o gancho beforeCreate. Devido a essa operação, cada instância de vm chamará o método vuexInit. Então, o que vuexInit faz?

vuexInit ()

Quando usamos Vuex, precisamos passar o armazenamento para a instância Vue.

new Vue({

  el: '#app',

  store

});

Mas podemos acessar a loja em cada vm, isso requer 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

    }

  }

Quando o nó raiz existe stroe, atribua diretamente options.store a este. $ Store. Caso contrário, não é o nó raiz e é obtido do $ store do nó pai.

Por meio dessa etapa, podemos acessar a instância Store por meio deste. $ Store em qualquer vm. A seguir, vamos falar sobre Vue.mixin () ao contrário.

Vue.mixin ()

Registre um mixin globalmente, afetando cada instância do Vue criada após o registro. Os autores de plug-ins podem usar mixins para injetar comportamentos personalizados nos componentes. Não recomendado para uso em código de aplicativo.

O método initMixin $ 1 (Vue) é chamado no método de entrada initGlobalAPI de vue:

function initMixin$1 (Vue) {

  Vue.mixin = function (mixin) {

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

    return this

  };

}

O processo do Vuex injetando o ciclo de vida do Vue é provavelmente assim. Se você estiver interessado, pode olhar diretamente no código-fonte do Vuex. A seguir, vamos falar sobre Store.

Loja

Mencionamos acima que vuexInit obterá Store de opções. Então, de onde vem a Store?

Quando usarmos Vuex, definiremos uma instância de Store semelhante à seguinte.

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,

})

Não habilite o modo estrito no ambiente de publicação. O modo estrito monitorará profundamente a árvore de estado para detectar mudanças de estado não compatíveis - certifique-se de desligar o modo estrito no ambiente de lançamento para evitar perda de desempenho.

Estado responsivo

Você se importa com o quão responsivo é o estado? Isso é obtido principalmente por meio do método resetStoreVM (this, state) chamado no construtor Store.

Este método serve principalmente para redefinir um objeto _vm privado (uma instância de Vue). Este objeto _vm manterá nossa árvore de estados e armazenará getters de armazenamento por meio de cálculos de atributos. Agora, vamos dar uma olhada em seu processo de implementação em detalhes.

/* 使用 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())

  }

}

O estado de resposta provavelmente é implementado desta forma, que é o processo de inicialização do método resetStoreVM.

Veja o método de confirmação de Store

Sabemos que o método commit é usado para acionar a mutação.

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 executa primeiro a verificação de estilo de parâmetro e, em seguida, usa o método _withCommit para executar esta função de processamento de mutação de gatilho em lote. Após a conclusão da execução, notifique todos os _subscribers (função de assinatura) sobre o objeto de mutação desta operação e o estado atual.

Plano de produção de artigos relacionados ao Vue

Recentemente, amigos sempre me perguntaram sobre questões relacionadas ao Vue, então irei publicar 9 artigos relacionados ao Vue a seguir, na esperança de ajudá-lo. Manterei uma atualização em 7 a 10 dias.

  1. [Dicionário de front-end] O processo de injeção do Vuex no ciclo de vida do Vue

  2. [Dicionário de front-end] Análise do princípio responsivo do Vue

  3. [Dicionário de front-end] O processo de patch de VNodes novos e antigos

  4. [Dicionário de front-end] Como desenvolver componentes funcionais e fazer upload de npm

  5. [Dicionário de front-end] Otimize seu projeto Vue a partir desses aspectos

  6. [Dicionário de front-end] Fale sobre o desenvolvimento de roteamento de front-end a partir do design do Vue-Router

  7. [Dicionário front-end] Como usar o Webpack corretamente no projeto

  8. [Dicionário de front-end] Renderização do servidor Vue

  9. [Dicionário de front-end] Como escolher entre Axios e Fetch

Eu sugiro que você preste atenção à minha conta oficial, você pode receber os artigos mais recentes o mais rápido possível.

[Dicionário de front-end] O processo de injeção do Vuex no ciclo de vida do Vue

Se você deseja ingressar na comunicação em grupo, também pode adicionar meu wqhhsd do WeChat.

Acho que você gosta

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