Исходный код Vuex: углубимся в модуль vuex

внешний интерфейс Vue.js Vuex

предисловие

храните состояние приложения вместе, но если приложение становится очень сложным, это состояние очень долгое, хранилище может сильно раздуться. модуль может помочь сохранить разделение модулей, каждый модуль имеет свое состояние, геттер, мутацию, действие и модуль.

Итак, как модуль разделен и как разделенный модуль управляет своим состоянием? Далее, давайте интерпретируем реализацию модуля.

Подготовить

Перед чтением необходимо овладеть следующими знаниями:

  1. Array.prototype.reduce()
  2. Vue.set()

интерпретировать

В документации vuex есть предложение: По умолчанию действия, мутации и геттеры внутри модулей регистрируются в глобальном пространстве имен — это позволяет нескольким модулям реагировать на одну и ту же мутацию или действие.

Что это значит? Взгляните на следующий пример:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    addNote () {
      console.log('root addNote')
    }
  },
  modules: {
    a: {
      state: {
        count: 0
      },
      mutations: {
        addNote () {
          console.log('module a addNote')
        }
      }
    }
  }
})

После использования модуля состояние модульно. Например, чтобы вызвать состояние корневого модуля, вызовитеstore.state.count, если состояние модуля должно быть вызвано, тоstore.state.a.count.

Но мутация в примере регистрируется глобально, то есть вызовstore.commit('addNote'), который вызовет мутацию для следующего модуля и модуля a. Если имена каждой мутации модуля не различаются, в случае одного и того же имени вызов будет инициироваться до тех пор, пока он зафиксирован.

Конечно, добавлены более поздние версии vuex 2.0.0.命名空间Функция делает модуль более модульным.

Таким образом, в модуле, который будет интерпретирован следующим, на самом деле, пока состояние является модульным, действие, мутация и геттер все еще находятся в глобальном модуле.

регистрация модулей

Регистрация модуля реализована в installModule, который находит метод installModule.

function installModule (store, rootState, path, module, hot) {
  const isRoot = !path.length
  const {
    modules
  } = module

  // set state
  if (!isRoot && !hot) {
    const parentState = getNestedState(rootState, path.slice(0, -1))
    const moduleName = path[path.length - 1]
    store._withCommit(() => {
      Vue.set(parentState, moduleName, state || {})
    })
  }
  
  // mutation 的注册
  // action 的注册
  // getter 的注册

  if (modules) {
    Object.keys(modules).forEach(key => {
      installModule(store, rootState, path.concat(key), modules[key], hot)
    })
  }
}

Глядя на упрощенный код, можно увидеть, что installModule выполняет двухэтапную операцию инициализации модуля. Первым шагом является использованиеVue.set()Состояние текущего модуля настроено для мониторинга; второй шаг — продолжить обход подмодулей, а затем рекурсивно вызвать installModule.

set state

Таким образом, основная реализация модулей заключается в установке монитора текущего состояния модуля и извлечении этого кода:

const parentState = getNestedState(rootState, path.slice(0, -1))
const moduleName = path[path.length - 1]
store._withCommit(() => {
  Vue.set(parentState, moduleName, state || {})
})

Сначала предположим, что метод getNestedState может получить родительское состояние. Итак, сначала получите родительское состояние, затем получите текущее имя модуля и, наконец, используйте Vue.set(), чтобы установить текущее состояние под родительским состоянием. На самом деле реализация заключается в добавлении атрибутов в data.state экземпляра vue и включении экземпляра vue для отслеживания изменений в добавленных атрибутах.

getNestedState

const parentState = getNestedState(rootState, path.slice(0, -1))

Удалите текущий модуль через path.slice(0, -1), передайте его в метод getNestedState в качестве параметра и корневого состояния rootState и верните родительское состояние parentState текущего модуля.

Давайте посмотрим на реализацию getNestedState:

function getNestedState (state, path) {
  return path.length
    ? path.reduce((state, key) => state[key], state)
    : state
}

Если длина равна 0, то есть только корневое состояние, возврат напрямую. Другой случай, если есть вложенные модули, то пройтиArray.prototype.reduce()Метод берет состояние, соответствующее пути, из свойства корневого состояния и возвращает его.

Пока модульность состояния была зарегистрирована, а затем рекурсивно вызовите installModule для завершения регистрации всех модулей.

Поскольку вы добавляете свойства в rootState, вы можете получить модуль через store.state.a, а затем продолжить получать состояние в модуле.

get modules state

При интерпретации мутации и действия ранее метод getNestedState был опущен. Регистрация мутаций и действия появится следующий код:

getNestedState(store.state, path)

По сути, этот код должен получить состояние текущих модулей и вернуть его в качестве параметра.

хранить массив

Я до сих пор помню при интерпретации мутации, почему мутация сохраняется в массиве store._mutations. Основная цель — сохранить мутации во всех модулях в массиве, чтобы все мутации можно было запускать при фиксации.

Это также причина, по которой геттеры и действия хранятся в массивах.

Однако, если два модуля имеют одинаковое имя мутации, vuex 2.0.0 не может вызвать только одну из мутаций. Это будет установлено в будущих версиях命名空间Может достичь.

Суммировать

Эта статья представляет собой интерпретацию модуля. Регистрация модуля не так сложна, как вы думаете, в основном она делится на два этапа.

Первый шаг — найти родительское состояние текущего модуля, а затем связать с ним по крайней мере слушателя текущего состояния, чтобы гарантировать, что изменение состояния вызовет ответ.

Второй шаг — рекурсия модуля, чтобы убедиться, что состояние подмодуля установлено, чтобы реализовать подвложенность модуля.