这是我个人的使用偏好,而且是以抽象资料型别的使用方式来理解 vuex 的使用方式。也许,我是说也许啦!和官网的不太一样。
昨天介绍了物件设计的核心原则,就是不要直接修改资料,务必要透过抽象行为来修改,以保持弹性与添加限制的同时,可以维护概念整体性。
这个原则,在後端也适用於 MVC 的 Module
Mutations | Vuex 的开章明义就说,想要改变 state ,就要 over my dead body (透过 mutation)。
The only way to actually change state in a Vuex store is by committing a mutation.
所以,其实 mutation 本身就隐含着 setter 的任务。必须单纯的修改值,并且适时的可以加入定义域限制。
「mutation 是唯一可以改变 state 的角色」,意思是说改变的同时要可以触发修改画面。所以,修改的原则,也是要符合 immutable,或者用 Vue 提供的 API Vue.set(obj, 'newProp', 123)
Use
Vue.set(obj, 'newProp', 123)
, orReplace that Object with a fresh one. For example, using the object spread syntax (opens new window)we can write it like this:
state.obj = { ...state.obj, newProp: 123 }
不过我觉得「靠自己,好自在」。所以只要修改值,就要注意 immutable,以及触发自动修改画面的机制 (符合 MVVM 的精神)
通常 mutation 是在接受 Web API 之後将 Web API 的资料 (通常是 GET 的 API) 储存到 state。
而这个步骤就足以决定你的 vuex 管理是否简单或复杂。
请遵守这些原则
命名不要用动词
命名要与 getters 同名
命名要注意单数/复数
因为使用的时候是
this.$store.commit('user', data)
this.$store.commit('users', data)
光这一行,你看得出什麽样的资讯?看不出什麽样的资讯呢?
看得出这样的资讯就够了。
至於 set 进 user 需不需要定义域的阻挡逻辑,通常 API 来的资料,都已经通过画面的栏位验证以及後端在接收到 POST 的时的验证,资料经过了这些验证而进入资料库,所以在取得资料时,其实应该相信这些机制的作用,不用在这个环节再阻挡或验证一次。
但如果,你的 commit 是直接透过画面把值设定进来,也许需要在 Mutation 加入验证,因为要确保 state 是正确的,才不会影响 getters 在输出资料时,还要写更多的逻辑处理。
官网的 Actions 说,它可以写非同步行为,而且要用 action 呼叫 mutation
mutation 不要写非同步行为
不要用 action 直接改 state
官网说建议要透过 action 呼叫 mutation 的理由,是万一你要非同步的使用 mutation 的话,就可以直接添加在 action。
我自己的解读是「如果没有要非同步,直接 commit 也是可以」
所以,我自己的用法会是「同步行为与非同步行为,分成 action 和 muation」
如果看见这样写
this.$store.dispatch('fetchUsers')
就是它要发一个 API 去请求 User 的列表,并且会在里面呼叫 commit('users', res.data)
将 response 的 body 储存在 state 里。
如果看见这样写
this.$store.commit('users', users)
就只是将资料储存到 state 里。
如果看见这样写
this.$store.dispatch('users', users)
我会不知道,这是非同步的还是同步的行为,中间经造了什麽将 users 储存到 state 里。
请遵守这些原则
命名要加上动词
以 User Module 为例 action 的命名会依 API 的用途为主。CRUD 的话已经有一定的命名原则。
行为 | 命名 | 实际使用 |
---|---|---|
新增 | createUser | $store.dispatch('createUser') |
读取 | fetchUser | $store.dispatch('fetchUser', id) |
读取 | fetchUsers | $store.dispatch('fetchUsers') |
修改 | updateUser | $store.dispatch('updateUser', id) |
删除 | deleteUsers | $store.dispatch('deleteUsers') |
删除 | deleteUser | $store.dispatch('deleteUser', id) |
命名要具体的描述行为,不需与 API 相同
有时候网站会有一些留言的机制。而留言的目的也许有不同的 type
有时 API 的开法, type 并不是参数,而是 path 的一部份
POST
/message/issue
POST
/message/comments
这个 issues 和 comments 就会把 actions 设计成
$store.dispatch('createMessage', { type, body })
comments | issue
这样 actions 的命名,是一种「使用非同步行为」的描述,而不只是非同步行为转变形式的样子
命名要注意单数/复数
名词的部份和 commit 一样,而且也是隐喻着要 commit 到哪里去。
根据 state 的状态衍生出其它的资料。
可以理解是一种共用的 computed 也可以理解是一种「整理资料的资料逻辑」
如果今天,在修改使用者 (ex: id=1
) user 的表单中,需要设定该 user 的主管,这个主管会是由一个下拉式选单来显示。
那麽资料该怎麽取得呢?
$store.dispatch('fetchUser', 1)
$store.dispatch('fetchUsers')
$store.getters.leaders
leaderOptions
(在 computed 里或 getters 也可以)取得主管的下拉式选单中,有一个 $store.getters.leaders
getters: {
leaders(state, getters) {
const departments = getters.departments;
return state.users.filter(user => departments.some(department => department.leader === user))
}
}
将整理资料的程序码写在 getters ,而不是在 mutation 的时候整理资料,有几个好处
mutation
第一个参数是 state (所属的 module 里的 state)
第二个参数是 payload (带什麽新东西要来修改值)?
mutation: {
user (state, payload) {
state.user = payload
}
}
getters
第一个参数是 state (所属的 module 里的 state)
第二个参数是跨 module 的 getters (不直接取得 state)
getters: {
leaders(state, getters) {
const departments = getters.departments;
return state.users.filter(user => departments.some(department => department.leader === user))
}
}
actions
第一个参数是 context 跨 module 取得 dispatch, commit, getters (不直接取得 state)
第二个参数这次传进来的参数,用起来和 mutation 的 payload 一样。
actions: {
fetchUser ({ dispatch, commit, getters }, user_id) {
// ...
}
}
透过观察参数可以发现 mutation 和 getters 的设计,修改/读取都是以 state 为核心。而 actions 比较像是面对这些 module 的独立 function 。有点像是後端的 controller。
所以,我在使用 vuex 的资料夹规画上面。只会把 actions.js 独立成一个档案。state
, mutation
, getters
这三样,会是放在一起的,形成了一个有自己 getter/setter 的抽象资料型别。
<<: Day27 过不去的槛就先绕过它 - LINE Notification
正文 今天最後一天了,当初因为没存稿的关系,加上很多主题想写,但又没把握能写好,所以不知道能不能顺利...
今晚来点轻松的。资料视觉化,复习一下DataFrame、seaborn 引用资料来源:country...
原始题目 You are given a large integer represented as ...
(这篇会延续Constructor Function的内容,来解释 Prototype 和 Prot...
上一篇我们学到怎麽使用Vim,还有修改commit message,这次要做的事情呢,就是要来合并跟...