предисловие
Компонентное построение приложений — одна из характеристик Vue, поэтому нам часто нужно инкапсулировать пользовательские компоненты в фактический процесс разработки Vue, чтобы повысить эффективность разработки. В большинстве случаев компоненты не существуют изолированно, и они неизбежно будут взаимодействовать с родительскими и одноуровневыми компонентами. Итак, вот краткий обзор двух способов взаимодействия компонентов с данными: EventBus и управление состоянием с использованием фреймворка Vuex.
В предыдущей статье было показано, как передавать события в пользовательских компонентах Vue через EventBus (Доставка событий пользовательских компонентов Vue: раздел EventBus), а EventBus больше подходит для использования в небольших и средних проектах; если нам нужно разработать масштабный проект, мы должны рассмотреть возможность использования фреймворка Vuex для унифицированного управления состоянием данных.
Чтобы помочь читателям понять основы использования Vuex, я продолжу использовать случай из предыдущей статьи (очевидно, что в одностраничных и малых и средних приложениях Vuex не нужен), чтобы представить использование Vuex.
Зачем использовать Vuex с EventBus
Зачем нам нужно использовать Vuex, когда у нас есть EventBus?
На самом деле, на официальном сайте Vuex есть хорошее объяснение:Официальный сайт Vuex объясняет, что такое Vuex
Что касается Vuex, я понимаю:
Vuex — это инфраструктура управления состоянием данных, которая в основном разделяет уровни данных и представления.
И EventBus уже есть, зачем нам Vuex, я так понимаю:
Давайте тщательно обдумаем это, когда мы используем EventBus, после того как наш элемент управления A передает данные элементам управления B и C, элементу B необходимо изменить переданные данные после обработки и продолжать уведомлять элементы управления A и C для изменения данных, поэтому что в файле C необходимо отслеживать EventBus A и B в нескольких местах. Таким образом, когда возникает ошибка при передаче данных, нам трудно отследить, какая ссылка неверна.
По мере увеличения сложности нашего бизнеса будет увеличиваться и сложность представления, поэтому в настоящее время очень необходимо отделить слои данных и представления через Vuex.
Введение к делу (в соответствии с предыдущим случаем «Доставка событий пользовательского компонента Vue: часть EventBus», можно пропустить)
В этой главе будет много примеров кода.Чтобы читателям было легко читать, мы вводим следующее содержание и компоненты. В этой главе в основном используются два дочерних компонента и один родительский компонент.
Имя файла подкомпонента:SearchInput.vueа такжеSearchItem.vue
Имя файла родительского компонента:StateView.vue
Отображение структуры каталогов:
1. SearchInput.vue
Введение компонента: поле ввода, оно будет отслеживать содержимое ввода с помощью метода onInput и вызывать метод для передачи данных в поле ввода.
Отображение кода:
<template>
<div>
<input placeholder="搜索内容" v-model="searchContent"/>
</div>
</template>
<script type="text/ecmascript-6">
export default{
data(){
return{
searchContent:""
}
},
props:{
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
SearchItem.vue
Введение компонента: диапазон, который в основном используется для получения содержимого, передаваемого родительским компонентом, и содержимого, передаваемого полем ввода родственного компонента, и его отображения.
Пример кода:
<template>
<span class="item">
{{content}}
</span>
</template>
<script type="text/ecmascript-6">
export default{
data(){
return{
content:this.itemContent
}
},
props:{
itemContent:{
type:String,
required:true
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.item
background #f4f4f4
padding 3px 5px
box-sizing border-box
display inline-block
cursor pointer
</style>
StateView.vue
Введение в компонент: родительский компонент, который в основном отображает страницы и загружает дочерние компоненты.
Пример кода:
<template>
<div>
<search-view></search-view>
<div>
<search-item :itemContent="content"/>
<search-item itemContent="热门搜索2"/>
<search-item itemContent="热门搜索3"/>
</div>
<div>{{content}}</div>
</div>
</template>
<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
export default{
data () {
return {
content:"接收输入框的值"
}
},
components: {
searchView,
searchItem
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
текст
Зарегистрируйте Vuex глобально
Прежде чем мы начнем знакомить с содержимым Vuex, нам нужно зарегистрировать объект Vuex в файле global.
Ознакомьтесь с нашей структурой каталогов:
1. Создайте файл магазина
Мы создали папку магазина для хранения различных типов файлов магазина.
Здесь мы создаем файл SearchStore.js. Это наш следующий главный герой, и вокруг него будут развиваться State, Getter, Mutation и Action Vuex.
Код SearchStore.js выглядит следующим образом:
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
})
2. Вставьте SearchStore.js в main.js
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import vueResource from 'vue-resource'
import searchStore from './store/SearchStore' //引入SearchStore.js
Vue.use(vueResource)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store:searchStore, //注入SearchStore
components: { App },
template: '<App/>'
})
Мы представили файл SearchStore.js в main.js и внедрили файл SearchStore.js в корневой компонент Vue, чтобы все дочерние компоненты могли получить доступ к магазину SearchStore.js.
State
Состояние похоже на глобальное хранилище данных, в котором хранятся источники данных.
Как понять эту фразу?
Не волнуйтесь, давайте посмотрим на демо-пример, и вы поймете состояние с первого взгляда.
мы модифицируемSearchStore.jsфайла, добавляем в него хранилище данных, то есть State:
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
state:{
searchContent:"这是Store的searchContent内容"
}
})
Тогда мыStateView.jsа такжеSearchInput.jsдля печати во время жизненного цикла mount()SearchStore.jsпоискКонтент в:
StateView
<template>
<div>
<search-view></search-view>
<div>
<search-item :itemContent="content"/>
<search-item itemContent="热门搜索2"/>
<search-item itemContent="热门搜索3"/>
</div>
<div>{{content}}</div>
</div>
</template>
<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
data () {
return {
content:""
}
},
mounted(){
console.log("StateView======"+this.$store.state.searchContent) //打印SearchStore中的searchContent
},
components: {
searchView,
searchItem
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
SearchInput.js
<template>
<div>
<input placeholder="搜索内容" @input="sendEvent" v-model="searchContent"/>
</div>
</template>
<script type="text/ecmascript-6">
import searchEvent from '../event/SearchEvent'
export default{
data(){
return{
searchContent:""
}
},
mounted(){
console.log("SearchInput======"+this.$store.state.searchContent)
},
props:{
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
консольный вывод
Как, вы чувствуете государство?
Вывод чувства государства:
1. Состояние — это хранилище данных, здесь будут храниться все источники данных, как и данные в компонентах.
2. Мы можем ясно чувствовать, что мыSearchStore.jsДанные в состоянии могут быть переданы в любой компонентthis.$store.state
Доступ вместо того, чтобы вызывать его везде, как с помощью EventBus$emit
а также$on
метод для мониторинга данных и копирования копий данных, чтобы отделить слои данных и представления.
Getter
Getter используется для обработки источника данных в определенной степени, прежде чем возвращать его при получении источника данных.
Далее мыSearchStore.jsДобавьте Getter, чтобы понять, что означает приведенное выше предложение.
SearchStore.js
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
state:{
searchContent:"这是Store的searchContent内容"
},
getters:{ //在这里加入getter
getSearchContent(state){
//我们定义了一个getter函数,叫做gerSearchContent,它有一个参数,这个参数保存了state对象。
//即SearchStore.js的state对象
return "加工后的searchContent===="+state.searchContent //模拟加工数据,并将加工后的数据返回
}
}
})
Здесь мы определяем функцию getSearchContent в геттерах Store, эта функция получает параметр, этот параметр является нашим объектом состояния, в данном случае: объектом состояния SearchStore.js.
Затем мы моделируем процесс обработки данных и возвращаем обработанные данные.
Далее, давайте напечатаем этот геттер в жизненном цикле mount() StateView.
StateView.js
<template>
<div>
<search-view></search-view>
<div>
<search-item :itemContent="content"/>
<search-item itemContent="热门搜索2"/>
<search-item itemContent="热门搜索3"/>
</div>
<div>{{content}}</div>
</div>
</template>
<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
data () {
return {
content:""
}
},
mounted(){
console.log("StateView======"+this.$store.state.searchContent) //打印SearchStore中的searchContent
console.log("StateView======"+this.$store.getters.getSearchContent) //打印SearchStore中的getSearchContent
},
components: {
searchView,
searchItem
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
консольный вывод
Заключение чувства Геттера
1. Геттер в основном используется для обработки данных и их возврата при получении данных.
2. По сравнению с EventBus, через Getter of Vuex мы можем единообразно обрабатывать данные в Store, что способствует дальнейшему обслуживанию проекта.
Mutation
Измените данные в хранилище данных. Мутация поддерживает только синхронные методы
Точно так же мы чувствуем роль Mutation, добавляя Mutation в SearchStore.js.
SearchStore.js
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
state:{
searchContent:"这是Store的searchContent内容"
},
getters:{
getSearchContent(state){
return "加工后的searchContent===="+state.searchContent
}
},
mutations:{
changeSearchContent(state,payload){
/**
* 传递单个数据参数
*/
state.searchContent=payload //修改state的searchContent数据
},
changeSearchContentByObject(state,payload){
/**
* 有时候我们需要再payload传递多个数据参数时,我们可以通过对象的方式传递
*/
state.searchContent="通过Object对象来修改数据:"+payload.searchContent
}
}
})
Уведомление: Выше мы определили два метода мутации. Единственное различие между ними заключается в том, что принимаемая полезная нагрузка представляет собой один параметр; когда необходимо передать несколько параметров, мы можем передать объекты в полезной нагрузке для передачи нескольких параметров.
Далее мы все еще модифицируем StateView.js.
StateView.js
<template>
<div>
<search-view></search-view>
<div>
<search-item :itemContent="content"/>
<search-item itemContent="热门搜索2"/>
<search-item itemContent="热门搜索3"/>
</div>
<div>{{content}}</div>
</div>
</template>
<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
data () {
return {
content:""
}
},
mounted(){
console.log("StateView======"+this.$store.state.searchContent) //打印SearchStore中的searchContent
console.log("StateView======"+this.$store.getters.getSearchContent) //打印SearchStore中的getSearchContent
//通过this.$store.commit()方法修改state的searchContent参数
//在payload中传递单个参数
this.$store.commit("changeSearchContent","StateView中修改后的SearchContent")
console.log("StateView======"+this.$store.state.searchContent)
//当需要传递多个参数时,我们可以在payload中以对象的形式传递
this.$store.commit("changeSearchContentByObject",{"searchContent":"StateView中修改后的SearchContent","testVal":"testVal"})
console.log("StateView======"+this.$store.state.searchContent)
},
components: {
searchView,
searchItem
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
существуетStateVie.js, мы проходимthis.store.commit()
метод для вызова метода в мутациях, который принимает два параметра:
1. Первый параметр передает соответствующее имя метода в мутациях 2. Второй параметр передает полезную нагрузку, то есть данные, которые необходимо передать
консольный вывод
Вывод о чувстве мутации:
1. С помощью Mutation мы можем изменить данные в хранилище данных, мы можем вызватьthis.$store.commit()
метод для вызова соответствующей мутации для изменения данных.
2. В Mutation можно выполнять только синхронные методы.Если нам нужно выполнить асинхронные методы, нам нужно использовать действие, которое появится рядом.
Action
Действие и Мутация похожи, они: 1. Действие подчиняет мутацию, а не прямое изменение состояния. 2. Действие может содержать любую асинхронную операцию.
Без лишних слов давайте изменим файл SearchStore.js напрямую:
SearchStore.js
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
state:{
searchContent:"这是Store的searchContent内容"
},
getters:{
getSearchContent(state){
return "加工后的searchContent===="+state.searchContent
}
},
mutations:{
changeSearchContent(state,payload){
/**
* 传递单个数据参数
*/
state.searchContent=payload //修改state的searchContent数据
},
changeSearchContentByObject(state,payload){
/**
* 有时候我们需要再payload传递多个数据参数时,我们可以通过对象的方式传递
*/
state.searchContent="通过Object对象来修改数据:"+payload.searchContent
}
},
actions:{
changeSearchContentByAction(context,payload){
/**
* 模拟异步的过程,2000毫秒后通过commit()方法执行mumations中的changeSearchContentByObject方法改变数据
* 同样,payload可以是单数据或通过对象的方式,传递多个数据
* 这里只举例通过对象传递多数据的情况
*/
setTimeout(()=>{
context.commit("changeSearchContentByObject",payload)
},2000)
}
}
})
Здесь мы имитируем асинхронный процесс, вызываяsetTimeOut()
функция, после 2000 мс, вызвавcommit()
для изменения данных searchContent.
Далее давайте изменим StateView.js, чтобы он вызывал то, что мы только что написали.changeSearchContentByAction
StateView.js
<template>
<div>
<search-view></search-view>
<div>
<search-item :itemContent="content"/>
<search-item itemContent="热门搜索2"/>
<search-item itemContent="热门搜索3"/>
</div>
<div>{{content}}</div>
</div>
</template>
<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
data () {
return {
content:""
}
},
mounted(){
console.log("StateView======"+this.$store.state.searchContent) //打印SearchStore中的searchContent
console.log("StateView======"+this.$store.getters.getSearchContent) //打印SearchStore中的getSearchContent
//通过this.$store.commit()方法修改state的searchContent参数
//在payload中传递单个参数
this.$store.commit("changeSearchContent","StateView中修改后的SearchContent")
console.log("StateView======"+this.$store.state.searchContent)
//当需要传递多个参数时,我们可以在payload中以对象的形式传递
this.$store.commit("changeSearchContentByObject",{"searchContent":"StateView中修改后的SearchContent","testVal":"testVal"})
console.log("StateView======"+this.$store.state.searchContent)
//通过Action修改数据
this.$store.dispatch("changeSearchContentByAction",{"searchContent":"action修改后的数据"})
setTimeout(()=>{
console.log("5000毫秒后StateView======"+this.$store.state.searchContent)
},5000)
},
components: {
searchView,
searchItem
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
Мы в StateView.js, черезthis.$store.dispatch()
для вызова действия, функция принимает два параметра:
1. Имя метода, соответствующее действию в магазине.
2. Данные для передачи
** Результаты вывода консоли **
Вывод чувства действия:
1. Действие похоже на мутацию, оно может обрабатывать только асинхронные ситуации и, наконец, проходитcommit()
Функция вызывает Mutation для изменения данных.
2. Пройтиthis.$store.dispatch()
Чтобы вызвать метод Action.
Module
Магазины могут быть модульными, а затем интегрированы через модули.
Если мы записываем все данные в состояние Store, то мы получаем и модифицируем данные. По мере того, как проект продолжает расти, количество состояний и мутаций, геттеров, действий в нашем магазине и количество строк кода в магазине будут стремительно увеличиваться, что усложнит поддержку нашего магазина.
В настоящее время мы надеемся разделить Store на модули, например, извлекать данные из разных подкомпонентов и записывать их в отдельный Store.
В это время нам нужно интегрировать каждый модуль через Module, а затем повесить Store под корневой компонент.
Теперь мы не используем SearchStore в качестве примера, мы создаем 3 новых файла Store:
1. Магазин index.js, который в основном отвечает за интеграцию всех модулей Магазина.
2. SearchInputStore.js, в основном отвечающий за обслуживание данных подкомпонента поля ввода SearchInput.js.
3. SearchItemStore.js, в основном отвечающий за обслуживание данных подкомпонентов SearchItem.js.
Сначала давайте посмотрим на SearchInputStore.js и SearchItemStore.js:
SearchInputStore.js
export default {
state: {
searchContent:""
},
getters:{
getSearchContent(state){
return state.searchContent;
}
},
mutations:{
changeSearchContent(state,payload){
state.searchContent=payload
}
}
}
SearchItemStore.js
export default {
state: {
searchHistoryList:[]
},
getters:{
getsearchHistoryList(state){
return state.searchHistoryList;
}
},
mutations:{
changesearchHistoryList(state,payload){
state.searchContent.push(payload)
}
}
}
Здесь мы просто проходимexport default
Вывод SearchInputStore и SearchItemStore.
Далее посмотримindex.js, Так и будетSearchInputStore.jsа такжеSearchItemStore.jsобъединены вместе
index.js
/**
* Created by Vicky on 2018/6/22.
*/
import Vue from 'vue'
import vuex from 'vuex'
import searchInputStore from './SearchInputStore'
import searchItemStore from './SearchItemStore'
Vue.use(vuex)
export default new vuex.Store({
modules:{
searchInputStore:searchInputStore,
searchItemStore:searchItemStore
}
})
В индексе мы сначала помещаемSearchInputStore.jsа такжеSearchItemStore.jsВводится импортом, а потом в Магазинеmodules
Представьте их обоих.
Далее мы смонтируем index.js под корневым компонентом и изменим main.js:
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import vueResource from 'vue-resource'
import store from './store/index' //引用index.js
// import searchStore from './store/SearchStore'
Vue.use(vueResource)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store, //修改部分,简写
components: { App },
template: '<App/>'
})
Таким образом, мы успешно интегрировали два модуля Store,Следует отметить, что когда мы обращаемся к объекту объекта состояния next, нам нужно добавить имя модуля:
Например, когда мы хотим получить доступ к данным searchContent SearchInputStore, нам нужно использоватьthis.$store.state.searchInputStore.searchContent
получить доступ.
namespaced: true
namespaced в основном используется для улучшения инкапсуляции и возможности повторного использования модулей.
Мы столкнемся с ситуацией, когда могут быть Mutation, Getter и Action с одинаковым именем метода в Store наших разных модулей.В это время мы вызываемcommit()
Будут вызваны все мутации с одинаковым именем метода; когда имя нашего метода Getter повторяется, будет сообщено об ошибке; когда мы вызываемdispatch()
будут выполнены все действия с тем же именем метода.
Это явно неразумно, и это приведет к загрязнению и исключениям данных других модулей. Но в крупномасштабном проекте мы часто разрабатываем совместно с несколькими людьми, поэтому нам трудно избежать того, чтобы каждый определял Mutation, Getter и Action одним и тем же именем, не будучи информированным.
На данный момент нам нужно пространство имен, чтобы помочь нам улучшить инкапсуляцию и возможность повторного использования модулей.
Далее мы модифицируемindex.js,SearchInputStore.jsдокумент:
index.js
import Vue from 'vue'
import vuex from 'vuex'
import searchInputStore from './SearchInputStore'
import searchItemStore from './SearchItemStore'
Vue.use(vuex)
export default new vuex.Store({
state:{
rootVal:"根节点Store的值"
},
getters:{
getRootVal(state){
return state.rootVal
}
},
mutations:{
changeRootVal(state,payload){
console.log("根节点Store的changeRootVal被调用了")
state.rootVal=payload
}
},
actions:{
changeRootValByAction(context,payload){
console.log("根节点Store的changeRootValByAction被调用了")
context.commit("changeRootVal",payload)
}
},
modules:{
searchInputStore:searchInputStore,
searchItemStore:searchItemStore
}
})
Мы добавили State, Getter и Mutation в index.js, чтобы продемонстрировать, как вложенное хранилище может получить доступ к Getter корневого хранилища после того, как вложенное хранилище инкапсулирует модуль данных через пространство имен,commit()
вызов корневой мутации и дочерней мутации; как передатьdispatch()
Вызовите корневое действие и дочерние действия.
SearchInputStore.js
export default {
namespaced:true,
state: {
searchContent:""
},
getters:{
getSearchContent(state,getters,rootState,rootGetters){
/**
* state 代表了当前模块的state
* getters 代表了当前模块的getters
* rootState 代表了根Store的state,即index.js的Store,但也包含它的子Store,我们可以通过rootState.searchInputStore访问searchItemStore;通过rootState.rootVal访问根模块的State值。
* rootGetters 代表了根Store的getters和它子Store的getter方法也会被挂载在rootGetters下,
* 我们可以通过rootGetters["searchItemStore/getHistoryList"]去访问searchItemStore模块下的getHistoryList
* 通过rootGetters.getRootVal去访问根模块的getRootVal
*/
//通过rootState去访问searchItemStore的State数据
console.log(rootState.searchItemStore.searchHistoryList)
//通过rootState去访问index.js的State数据
console.log(rootState.rootVal)
//通过rootGetters去访问searchItemStore的Getter
console.log(rootGetters["searchItemStore/getHistoryList"])
//通过rootGetters.getRootVal去访问根模块的getRootVal
console.log(rootGetters.getRootVal)
return state.searchContent;
}
},
mutations:{
changeSearchContent(state,payload){
/**
* state 代表了当前模块的state
* payload 代表了传入的数据
*/
//this.commit("searchItemStore/changeHistoryList",payload)调用SearchItemStore根模块的changeHistoryList
this.commit("searchItemStore/changeHistoryList",payload)
//通过this.commit("changeRootVal",payload)调用根模块的changeRootVal
this.commit("changeRootVal",payload)
console.log("changeSearchContent被调用了")
state.searchContent=payload
}
},
actions:{
changeSearchContentByAction(context, payload){
//调用本模块的changeSearchContent
context.commit("changeSearchContent",payload)
//调用本模块的otherAction
context.dispatch("otherAction",payload)
//调用根节点的Mutation和Action只需要传入第三个参数对象,{root:true}即可
context.commit("changeRootVal",payload,{root:true})
//调用根节点的changeRootValByAction
context.dispatch("changeRootValByAction",payload,{root:true})
},
otherAction(context,payload){
console.log("otherAction被调用")
}
}
}
SearchItemStore
export default {
namespaced:true,
state: {
searchHistoryList:["历史记录1"]
},
getters:{
getHistoryList(state){
return state.searchHistoryList;
}
},
mutations:{
changeHistoryList(state,payload){
state.searchHistoryList.push(payload)
}
},
actions:{
changeHistoryListByAction(context,payload){
context.commit(changeHistoryList,payload)
}
}
}
мы проходимnamespaced:true
для инкапсуляции модуля.
потому чтоSearchInputStoreа такжеSearchItemStoreИнкапсуляция, как наши подкомпоненты должны получить доступ к SearchInputStore? Как SearchInput получает доступ к состоянию, геттеру, мутации и действию других инкапсулированных модулей и корневого хранилища?
Как подкомпоненты получают доступ к инкапсулированному модулю (в качестве примера возьмем доступ к SearchInputStore)
состояние доступа
При доступе к инкапсулированным данным State нам нужно только внести следующие изменения** (в качестве примера возьмем searchContent of SearchInputStore)**:
this.$store.state.searchContent
изменить наthis.$store.state.searchInputStore.searchContent
Посетите Геттер
(В качестве примера возьмите доступ к getSearchContent из SearchInputStore):
this.$store.getters.getSearchContent
изменить наthis.$store.getters["searchInputStore/getSearchContent"]
Посетите мутацию
(В качестве примера возьмите доступ к changeSearchContent SearchInputStore):
this.commit("changeSearchContent","新数据")
изменить наthis.$store.commit("searchInputStore/changeSearchContent","新数据")
Доступ к действию
(В качестве примера возьмем changeSearchContentByAction для доступа к SearchInputStore):
this.dispatch("changeSearchContentByAction","新数据")
изменить наthis.$store.dispatch("searchInputStore/changeSearchContentByAction","新数据")
Как инкапсулированный модуль получает доступ к другим инкапсулированным модулям и корневому модулю (в качестве примера возьмем доступ к SearchItemStore)
Давайте подробнее рассмотрим следующий код SearchInputStore:
SearchInputStore
export default {
namespaced:true,
state: {
searchContent:""
},
getters:{
getSearchContent(state,getters,rootState,rootGetters){
/**
* state 代表了当前模块的state
* getters 代表了当前模块的getters
* rootState 代表了根Store的state,即index.js的Store,但也包含它的子Store,我们可以通过rootState.searchInputStore访问searchItemStore;通过rootState.rootVal访问根模块的State值。
* rootGetters 代表了根Store的getters和它子Store的getter方法也会被挂载在rootGetters下,
* 我们可以通过rootGetters["searchItemStore/getHistoryList"]去访问searchItemStore模块下的getHistoryList
* 通过rootGetters.getRootVal去访问根模块的getRootVal
*/
//通过rootState去访问searchItemStore的State数据
console.log(rootState.searchItemStore.searchHistoryList)
//通过rootState去访问index.js的State数据
console.log(rootState.rootVal)
//通过rootGetters去访问searchItemStore的Getter
console.log(rootGetters["searchItemStore/getHistoryList"])
//通过rootGetters.getRootVal去访问根模块的getRootVal
console.log(rootGetters.getRootVal)
return state.searchContent;
}
},
mutations:{
changeSearchContent(state,payload){
/**
* state 代表了当前模块的state
* payload 代表了传入的数据
*/
//this.commit("searchItemStore/changeHistoryList",payload)调用SearchItemStore根模块的changeHistoryList
this.commit("searchItemStore/changeHistoryList",payload)
//通过this.commit("changeRootVal",payload)调用根模块的changeRootVal
this.commit("changeRootVal",payload)
console.log("changeSearchContent被调用了")
state.searchContent=payload
}
},
actions:{
changeSearchContentByAction(context, payload){
//调用本模块的changeSearchContent
context.commit("changeSearchContent",payload)
//调用本模块的otherAction
context.dispatch("otherAction",payload)
//调用根节点的Mutation和Action只需要传入第三个参数对象,{root:true}即可
context.commit("changeRootVal",payload,{root:true})
//调用根节点的changeRootValByAction
context.dispatch("changeRootValByAction",payload,{root:true})
},
otherAction(context,payload){
console.log("otherAction被调用")
}
}
}
Состояние доступа и геттер
Первый взглядSearchInputStoreгеттеры:
Мы обнаружили, что параметры, принимаемые getSearchContent, менялись от состояния к состоянию, getters, rootState, rootGetters, и их значения следующие:
1. состояние представляет состояние текущего модуля
2. геттеры представляют геттеры текущего модуля
3. rootState представляет состояние корневого хранилища, то есть хранилища index.js, но также включает его вложенные хранилища.Мы можем получить доступ к searchItemStore через rootState.searchInputStore, получить доступ к значению состояния корневого модуля через rootState.rootVal .
4. rootGetters представляет геттеры корневого хранилища, и методы геттеров его подхранилищ также будут смонтированы в rootGetters, мы можем получить доступ к getHistoryList в модуле searchItemStore через rootGetters["searchItemStore/getHistoryList"]
Посетите мутацию
(В качестве примера возьмите доступ к changeSearchContent SearchInputStore):
В мутации SearchInputStore вы можете передать:
1. this.commit("searchItemStore/changeHistoryList",payload) вызывает changeHistoryList корневого модуля SearchItemStore
2. this.commit("changeRootVal",payload) вызывает changeRootVal корневого модуля
Доступ к действию
(В качестве примера возьмем changeSearchContentByAction для доступа к SearchInputStore):
В Action SearchInputStore можно вызывать Mutation и Action корневого модуля, но нельзя вызывать Mutation других инкапсулированных модулей, иначе будет сообщено об ошибке.
На самом деле это тоже имеет смысл.Когда Мутация этого модуля выполняется асинхронно, если мы хотим модифицировать данные других модулей, нам нужно только вызывать Мутации других модулей в Мутации нашего собственного модуля. необходимо вызвать другие модули.
Итак, мы можем пройти в этом модулеcontext.commit()
а такжеcotext.dispatch()
Чтобы вызвать мутацию и действие этого модуля и корневого модуля:
1. Вызовите changeSearchContent этого модуля:context.commit("changeSearchContent",payload)
2. Вызовите otherAction этого модуля:context.dispatch("otherAction",payload)
3. Чтобы вызвать Mutation и Action корневого модуля, вам нужно только передать третий объект параметра, {root:true}:context.commit("changeRootVal",payload,{root:true})
4, вызовите корневой модуль ChangerootValbyAction:context.dispatch("changeRootValByAction",payload,{root:true})
финальный повтор
1. Vuex — это фреймворк для разделения слоев данных и представлений.
2. Нет необходимости использовать Vuex в одностраничных и небольших проектах.
3. Состояние в Vuex похоже на глобальное хранилище данных, в котором хранятся источники данных.
4. Getter в Vuex используется для обработки источника данных перед его возвратом при получении источника данных.
5. Мутация в Vuex используется для изменения данных в хранилище данных. Mutation поддерживает только синхронные методы.
6. Действия в Vuex аналогичны мутациям: 1. Действия вызывают мутации вместо прямого изменения состояния. 2. Действие может содержать любую асинхронную операцию.
7. Модуль в Vuex может разбить Store на модули, а затем интегрировать его вместе через модуль.
8. Про...mapGetters,...mapMutation,...mapActions специально не расширяется, в основном для упрощения написания кода через синтаксис es6, можно обратиться к официальным документам:Официальная документация Vuex
9. После прочтения этого туториала из-за большого объема контента рекомендуется еще раз прочитать официальную документацию и самостоятельно реализовать небольшую демоверсию.
Я ячмень, если вам понравилась моя статья, пожалуйста, дайте мне сердце.