Vuex 核心模块
- 单一状态树,用一个对象就包含了全部的应用层级状态
- mapState 当一个组件需要多个状态的时候, 将这些状态都声明为计算属性,会有些重复和冗余
- 对象展开符号 …mapState({})
import {mapState} from 'vuex'
export default {
// mapState要写到computed上面 ,用了vuex之后就要把data给忘了.
computed: mapState({
count: state => state.count,
countAlias: "count",
countPlusLocalState(state) {
return state.count + this.localCount
}
})
// ...mapState({count}) 扩展函数符
}
- 从store 中的state中派生出一些状态
- mapGetters 辅助函数,仅仅是将store中的getters映射到局部计算属性
- getters (可以认为是store的计算属性)
const store = new Vuex.Store({
state: {
todos: [
{id: 1, text: '...', done: true},
{id: 2, text: '...', done: false},
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
// use:
,computed:{
doneTodosCount(){
// this.$store就是vuex 上面的
return this.$store.getters.doneTodos
}
}
// use:
,computed:{
...mapGetters([
'doneTodos'
])
}
- 更改Vuex的store中的状态,的唯一方式是提交mutation(不能直接调用句柄,必须通过触发)
- mutations 就是vue 中的methods
- 每一个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)
- 使用常量代替mutation事件类型
- mutation必须是同步函数
// mutation-type.js
export const SOME_MUTATION='SOME_MUTATION'
// store.js
import {SOME_MUTATION} from './mutation-type'
const store=new Vuex.Store({
state:{...},
mutations:{
// 接受一个常量作为Objeck对象的key.是es6的写法
[SOME_MUTATION](state){
//mutate state
}
}
})
然后调用
// use:
import {mapMutations} from 'vuex'
import {SOME_MUTATION} from './mutation-type'
export default {
methods:{
test(){
this.$store.commit(SOME_MUTATION)
},
...mapMutations([
'SOME_MUTATION'
// 映射thisincrement()为this.$store.commit('SOME_MUTATION')
])
}
}
- action提交的是mutation
- action可以包含任何异步操作
- mapActions辅助函数将组建的methods映射为store.dispatch调用
- view->store.dispatch(‘increment’)
- action->commit(‘someMutation’)
actions:{
async actionA({commit}){
commit('gotDate',await getDate())
},
async actionB({dispatch,commit}){
await dispatch('actionA')//等待actionA完成
//commit 可以带数据过去
commit('gotOtherData',await getOtherData())
}
}
// use:
import {mapActions} from 'vuex'
export default {
methods:{
test(){
store.dispatch('actionB')
},
...mapActions([
'actionB'
//映射this.incrment()
// this.$store.dispatch('actionB')
])
}
}
- vuex运行我们将store分割到模块(module).每个模块拥有自己的state,mutation,action,getters,甚至是嵌套子模块–从上至下进行类似的分割
- store创建之后,你可以使用store,registerModule方法注册模块
const moduleA={
state:{},
mutations:{},
actions:{},
getters:{}
}
const moduleB={
state:{},
mutations:{},
actions:{},
getters:{}
}
const store=new Vuex.Store({
modules:{
a:moduleA,
b:moduleB
}
})
// use:
store.state.a
store.state.b
附:
//动态注册一个module
store.registerModule('moduleC',{})
- vuex的store 接受plugins选项,这个选项暴露出每次mutation的钩子,vuex插件就是一个函数,他接收sotre作为唯一参数
- 在插件中不允许直接修改状态–类似于组建,智能通过提交mutation来触发变化;
- 自定义的状态快照
const myPlugin = store => {
// 当store 初始化后调用
store.subscribe((mutation,state)=>{
// 每次mutation之后调用
// mutation的格式为{type,payload}
})
}
// use
const store=new Vuex.Store({
plugins:[myPlugin]
})
- Vuex的思维处理表单
- 测试Action需要增加一个mocking服务层, 测试文件中用mock服务响应API调用,为例便于解决mock依赖,可以用webpack和inject-loader打包测试文件;
- Hot MOdule Replacement API, Vuex支持在开发过程中热重载mutation,mudules,actions 和getters.
// 测试Actions 演示
import {expect} from 'chai'
const actionsInjector=require('inject!./actions')
const actions=actionsInjector({
'../api/shop':{
getProducts(cb){
setTimeout(()=>{
cb([/*mocked response*/])
},100)
}
}
})
// 测试代码
describe('actions',()=>{
it("getAllProducts",done=>{
testAction(actions.getAllProducts,[],{},[
{type:'REQUEST_PRODUCTS'},
{type:'RECEIVE_PRODUCTS',payload:{}}
],done)
})
})
import {sync} from 'vuex-router-sync'
import store from './vuex/store'
import router from './router'
sync(store,router)
this.$store.state.route.path
this.$store.state.route.params
this.$store.state.route.query