(TODO)vuex学习笔记

看完官方文档后,可以先通过购物车项目熟悉下Vuex。

名词解释

store

state

getter

mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

一条重要的原则就是要记住 mutation 必须是同步函数

实质上任何在回调函数中进行的状态的改变都是不可追踪的。

mapMutations

action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态(这样就可以记录异步操作的成功/失败状态了)。
  • Action 可以包含任意异步操作。

module

初始化store

将组件的方法绑定到全局store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { mapMutations } from 'vuex'

export default {
// ...
methods: {
...mapMutations([
'increment', // map `this.increment()` to `this.$store.commit('increment')`

// `mapMutations` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // map `this.add()` to `this.$store.commit('increment')`
})
}
}

在组件内触发store的状态变更

State

Vuex uses a single state tree - that is, this single object contains all your application level state and serves as the “single source of truth”. This also means usually you will have only one store for each application.

mapState

we can make use of the mapState helper which generates computed getter functions for us, saving us some keystrokes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// in full builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'

export default {
// ...
computed: mapState({
// arrow functions can make the code very succinct!
count: state => state.count,

// passing the string value 'count' is same as `state => state.count`
countAlias: 'count',

// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}

如果不做其他计算,也不需要重命名,那么直接传入字符串数组即可:

1
2
3
4
computed: mapState([
// map this.count to store.state.count
'count'
])

Getters

Vuex allows us to define “getters” in the store. You can think of them as computed properties for stores. Like computed properties, a getter’s result is cached based on its dependencies, and will only re-evaluate when some of its dependencies have changed.

把Getters理解为store的computed属性即可。

mapGetters

The mapGetters helper simply maps store getters to local computed properties.

将store的getters的属性,和具体某个component的computed属性绑定,方便使用,比如这样:

1
2
3
4
5
6
7
8
export default {
computed: {
...mapGetters('cart', {
products: 'cartProducts',
total: 'cartTotalPrice'
})
}
}

如果不想重命名getters属性,传入的参数改为字符串数组即可:

1
2
3
4
5
6
7
8
export default {
computed: {
...mapGetters('cart', [
'cartProducts',
'cartTotalPrice'
])
}
}

模块(Module)

TODO:还没弄懂: https://vuex.vuejs.org/guide/modules.html

用途

命名空间

动态创建/删除模块

注意事项

Action和Mutation的区别

mutation action
触发方式 commit dispatch
执行方式 同步 同步、异步
对应Vue的属性 computed methods
map mapState mapActions

moduleA如何操纵moduleB的数据?

vuex.esm.js?2f62:419 [vuex] unknown action type: configs/getAllConfigs

加上namespaced: true,

TODO:为什么

组件的data属性能够和store的属性绑定么?

除了computed属性之外,还有其他办法么?

computed属性会缓存,直接用其替代data,似乎也没啥问题。

如果让computed返回一个store中的对象,在组件中修改这个对象的属性后,store中的属性会自动随着变更么?

computed中使用箭头函数的坑

错误(这里的this是undefined):

1
2
3
computed: mapState({
selectedAntonyms: state => this.restore(state.vocabulary.antonyms)
})

正确:

1
2
3
4
5
computed: mapState({
selectedAntonyms: function (state) {
this.restore(state.vocabulary.antonyms)
}
})

为什么computed属性变更后,页面元素没有自动变更?

因为computed属性,我忘记return了。

用了computed属性,那么修改这些属性就必须通过commit触发mutation方法

TODO:这样代码会很多,有更好的方案么?

比如我修改词汇对象的name、remark、sentences等等,都需要在组件中单独编写触发mutation的代码,很verbose.

而且还不能直接触发,还得是watch属性,那么又得额外写一个data属性,并且关联到store的属性,再去watch,太麻烦了。感觉我用得不对。

应该是在交互发生的处理函数中,去触发mutation。

也不对,应该是数据驱动,比如修改name,总不能再单独给input框绑定一个键盘事件吧?

感觉是我在设计store的时候就设计错了:只有需要传递的数据才放入store,针对这次的应用,只有tag。

其他的都应该作为组件自身的属性,写到组件的data中。

页面初始化的时候,由父组件请求数据,传入子组件,进行渲染。

这样无需编写太多computed属性,代码也更加清晰可读(大部分属性和逻辑都限制在组件内部)。