@lizlalala
2017-01-10T17:20:13.000000Z
字数 3393
阅读 1458
vuex
vue的坑
state
Vuex提供了机制,使得设置 store选项(启用Vue.use(Vuex))会将 store 从根组件『注入』到每一个子组件中。
const app = new Vue({
el: '#app',
// 使用 "store" 选项后,可以注册 store 对象。将会把 store 实例注入到所有子组件。
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
子组件中可以通过this.$store.state.someprop访问
mapState:
computed: mapState({
count: state => state.count,
countAlias: 'count',
'count',
countPlusLocalState (state) {
return state.count + this.localCount
}
})
或者用对象扩展方法将mapState作为computed的部分
computed:{
test1(){..},
...mapState({})
}
getters
类似于store的计算属性函数,接受state作为第一个参数
const store = new Vuex.Store({
state: {
},
getters: {
doneTodos: state => ...
}
})
组件中用this.$store.getters.blah访问
Mutations
actions
更新2
1. 需要注意的是,整个操作中只通过在store里面提交mutations来实现数据的更改,(便于用dev-统一tool去统一跟踪)。
2. 总的来说,vuex解决的是用纯数据交互的方式来处理原本属于组件间(sibling组件)的通信,有人会说那我用event也可以做到通信啊,但是当组件创建、销毁时,这些状态也随之变动,因此需要有一个独立于组件的状态树来进行维护。在知乎上看到一个回答,挺好的:
Vuex的主要作用是各组件间的状态同步(以及同一组件再次显示时的状态保持)。
特别是非数据库内容。比如网页右上角的搜索框,并不像日志列表那样对应数据库内容。
如果不希望每次进入有搜索框的模板页面,搜索框内容都被重置,那么就需要高于组件的架构
题外话:
以往的操作是:
- parentA
- childB
- childC
子组件(B,C)要调用A的回调,那么通过props传递到B,C即可。
A中要调用B.C的方法/属性,那么也可以通过props回调,然后把B,C的属性/方法作为参数 this.props.Afn(bVal,cVal,bFn,cFn)这样。(当然这是在B,C内部操作)。如果一定要在A中执行,可以this.ref.B.blah(以react为例)
在vue中,通信中props的部分跟react一样,当然也可以通过(特别是孙孙组件这种层级特别多的)事件,B,C中emit,A中on
而事件也适用于sibling之间的通信,如B,C。
栗子可以看react
以shopping-cart为例来分析vuex的goods
子组件为cart和products。购物车和商品列表。
[{
input: 'tet', //不会改变外部
select: ['test1','test2']//会作用于外部
}]
这样就违背了数据单向传递的目的,那么所有引用这个wigetList的值都会相应的被变化。
应该是props传递进来的时候用的浅复制,类似于Object.assign.
对每个key遍历赋值,然后基本类型都赋值,但是引用赋的还是对象。
一种解决方案是传递immutable数据(蠢蠢的方法是JSON序列化掉然后传进来...)。
还有一种是虽然传引用,但是赋值(data用props初始化的时候)用深拷贝(这边用的lodash的深拷贝)。
import cloneDeep from 'lodash/cloneDeep'
data() {
return {
showModal: this.show,
wigets: cloneDeep(this.wigetList), //here
form: {...wigetTest}
};
},
watch:{
show(val){
this.showModal = val;
},
wigetList(val){
this.wigets = cloneDeep(val); //here ~
}
//page1:
watch: {
'$route'(to,from) {
//监听tab导致的路由变动
if(to.query && to.query.tab){
this.$store.dispatch('changeTab',to.query.tab).then(()=>{
this.reset();
})
}
}
},
//根store
const actions = {
changeTab({commit},tab){
//返回一个promise
return new Promise((resolve,reject)=>{
commit(types.CHANGE_TAB,tab);
resolve();
})
}
}