首先先回顾一下上周提到的 Store 中有这些东西:
还记得上周取得资料的时候,我们直接使用 $store.state
在 computed 中直接抓资料吗?
当资料需要被处理过的话,当然也可以从 computed 中进行处理,例如以上周的 TodoList 例子来说,假设我需要计算有几笔是已完成的,就可以这样写:
computed: {
countTodoDone() {
let todolist = this.$store.state.todolist;
return todolist.filter((item) => {
return item.done === true;
});
},
},
那 getters 要干嘛xD?
当有多个地方需要用到相同的计算结果时,getters 就会现身~
而他的写法就跟 computed 一样:
getters: {
countTodoDone() {
let todolist = this.$store.state.todolist;
return todolist.filter((item) => {
return item.done === true;
});
},
},
准备好 getters 之後,在元件中就能使用 mapGetters()
的方式来取得计算结果罗~
//元件中先 import 它
import { mapGetters } from "vuex";
export default {
...,
computed: {
...mapGetters(["countTodoDone"]),
},
};
如果有多个 getters 要取得,就直接加在阵列中就好:
...mapGetters(["countTodoDone", "AAA", "BBB"]),
在大型专案中,不可能只存在一个元件,当有多个元件都要存取 Store,这时候就会容易发生冲突的状况
例如取了一样的资料名称或是方法名称等等
这时候就可以将 Store 进行模组化 modules ,分割成多个模组来解决这个困境
由於使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex允许我们将store分割成模块(module)。
而分割出来的每一个模组都各自包含自己的:
官网的模组化范例是这麽写的:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
可以看到范例中 moduleA 和 moduleB 各自有自己的内容,最後放进 Store 的 modules
不过我的观念是不会把模组和 Store 写在一起,因为这样全挤在一坨很恶心而且不好维护~
那要怎麽写呢?
我们拿昨天的 TodoList 来改改看吧~
首先,在 /store 资料夹里面新增一个档案 - todolist.js
src
└── store
├── index.js
└── todolist.js //新增这个档案
模组中该有的基本内容都加上去:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default {
state: { },
actions: { },
mutations: { },
getters: { }
};
注意这边汇出(export)的不是 Store 喔!!
有些菜鸟没注意到 (就是我)
把跟 TodoList 相关的内容全部移植过去:
export default {
state: {
todolist: [
{ id: 1, todo: "交女朋友", done: false },
{ id: 2, todo: "财务自由", done: false },
{ id: 3, todo: "当码农", done: true },
],
},
actions: {
todoDone(context, { id, done }) {
context.commit('TODOLIST', { id, done });
},
},
mutations: {
TODOLIST(state, { id, done }) {
state.todolist.find((item) => {
return item.id === id
}).done = done;
},
},
getters: {
countTodoDone() {
let todolist = this.$store.state.todolist;
return todolist.filter((item) => {
return item.done === true;
});
},
}
};
在 /store/index.js 主档中引用 todolist.js:
import TodoListModules from './todolist'
并且加进 modules:
export default new Vuex.Store({
...,
modules: {
RoomsModules,
TodoListModules,
},
});
开启 App.vue 在取得 Store 资料的部分要稍做修改
computed: {
myTodo() {
return this.$store.state.TodoListModules.todolist;
},
},
到这边暂停一下,这里模组化的内容中
state 是注册在 TodoListModules 命名空间中
而其他的 actions & mutations & getters 则是注册在全局命名空间
所以会发现就算 todoDone() 不加上模组也能呼叫:
methods: {
todoDone(id, done) {
this.$store.dispatch("todoDone", { id, done });
},
},
官方是这麽说明的:
默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的——这样使得多个模块能够对同一mutation或action作出响应。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加namespaced: true的方式使其成为带命名空间的模块。
当模块被注册後,它的所有getter、action及mutation都会自动根据模块注册的路径调整命名。
意思就是如果想让模组完整度高一点,可以加上 namespaced: true
这个属性,我们来加看看吧~
// /store/todolist.js
export default {
namespaced: true,
...,
};
这时候点清单会发现console跳错罗!!
///[vuex] unknown action type: todoDone
回到 todoDone() 来加上模组,就又正常罗~
methods: {
todoDone(id, done) {
this.$store.dispatch("TodoListModules/todoDone", { id, done });
},
},
到这就大功告成~ 完美移植TodoList模组化~
可以看一下画面一样可以动 哈哈xD
目前我研究到这而已~
已经可以把很多现有的专案改良了!!
其他功能,之後如果有再深入探讨的话再来发一篇吧~
>>: [ Day 36 ] - Electron 应用程序 - 更新自动化 ( 实做篇 )
一个Experiment的运行逻辑是: • Tuner 接收搜索空间,生成configuration...
此为番外,此篇选入番外的原因是 glob 并不是个工具,但是是个会常被各种工具采用的一种配置方式。...
终於结束Text的部分啦~~~ 今天要来讲Treeview,这个就是树状的意思,像树一样有层次感,可...
前言 函式用於结构化程序,将需要重复用到的功能独立出来,透过函式的呼叫,传入资料与回传处理後的资料。...
大家好我是 Gui,一名刚於私立科大资管系毕业的社会新鲜人,这是我第一次参与 IT 铁人赛,既紧张又...