vuex
::运用场景:根据项目规模判断::
不能直接改变store,改变store唯一途径就是显示地提交mutations。这样使得我们可以方便跟踪每一个状态的变化,从而让我们实现一些工具帮助我们更好的了解我们的应用
state
单一状态书,用一个对象就包含了全部的应用层级状态
- mapState 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余
- 对象展开符号 …mapState({{})
import { mapState } from 'vuex'
dexport default {
computed: mapState({
count: state => state.count,
countAlias: 'count',
countPlusLocalState (state) {
return state.count + this.localCount
}
// ...mapState({count}) 扩展函数符
})
}
getters
从store中的state 中派生出一些状态
- mapGetters 辅助函数仅仅是将store中的getters映射到局部计算属性
- 对state进行扩展,通过getters 进行设置 (相当于 computed,可以认为是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)
}
})
computed: {
doneTodosCount () {
return this.$store.getters.doneTodos
}
}
computed:{
...mapGetters([
'doneTodosCount'
])
}
mutations
- 更改Vuex的store中的状态的唯一方法是提交mutation(不能直接调用句柄,必须通过触发)
- mutations就是vue methods
- 每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)
- 使用常量替代Mutation事件类型
- mutation必须是同步函数
//mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
//store.js
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state:{...},
mutations:{
[SOME_MUTATION](state){
//mutate state
}
}
})
Mutations(调用篇)
import { mapMutations } from 'vuex'
import { SOME_MUTATION } from './mutation-types'
export default {
methods:{
test(){
this.$store.commit(SOME_MUTATION)
},
...mapMutations([
'SOME_MUTATION'
//映射 this.increment()为this.$store.commit('SOME_MUTATION')
])
}
}
actions
接受用户传过来的event
- 提交的是mutation
- 可以包含任何异步操作
- mapActions 辅助函数将组件的methods映射为store。dispatch调用
- view -> store.dispatch(‘increment’)
- action -> commit(‘someMutation’)
actions:{
async actionA({commit}){
commit('gotData',await getData())
},
async actionB({dispatch,commit}){
await dispatch('actionA') //等待actionA完成
commit('gotOtherData',await getOtherData())
}
}
Action 调用
import { mapActions } from 'vuex'
export default {
methods:{
test(){
store.dispatch('actionB')
}
},
...mapActions([
'actionB'
//映射 this.increment()
//this.$store.dispatch('actionB')
])
}
modules
- Vuex 运行我们将store分割到模块(module)。 每个模块拥有自己的state、mutation、action、getters甚至嵌套子模块——从上至下进行类似的分割
- store创建之后,你可以使用store.registerModule方法注册模块
const moduleA = {
state:{...},
mutations:{...},
actions:{...},
getters:{...}
}
const moduleB = {
state:{...},
mutation:{...},
action:{...}
}
const store = new Vuex.Store({
modules:{
a:moduleA,
b:moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
store.registerModule('myModule',{
// ...
})
plugins
- Vuex的store接受plugins选项,这个选项暴露出每次mutation的钩子。Vuex插件就是一个函数,它接受sotre作为唯一参数
- 在插件中不允许直接修改状态——类似于组件,只能通过提交mutation来触发变化
- 自定义的状态快照
//plugins 代码演示
const myPlugin = store => {
//当store初始化后调用
store.subscribe((mutation, state) => {
//每次 mutation 之后调用
// mutation 的格式为 {type, payload }
})
}
const store = new Vuex.Store({
plugins: [myPlugin]
})
Vuex 的思维处理表单
<input :value:"message" @input="updateMessage">- 测试Actions需要增加一个mocking服务层,测试文件中用mock服务回应API调用。为了便于解决mock依赖,可以用Webpack 和inject-loader打包测试文件
- Hot Module Replacement API ,Vuex 支持在开发过程中热重载 mutation、modules、actions、getters
测试Actions 演示
import { expect } from ‘chai'
const actionsInjector = require('inject!./actions')
// 使用mocks创建模块
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)
})
vuex-router-sync
(sync 同步、async异步) vue 视图 vuex 数据源 vue-router 路由 vuex-router-sync 连接vuex\vue-router
视图层
<div id="app">
<h1>Hello APP</h1>
<p>
<router-link to="/foo">go to foo</router-link>
<router-link to="/bar">go to bar</router-link>
</p>
<router-view></router-view>
</div>
结合Vuex
import { sync } from 'vuex-router-sync'
import store from './vuex/store'
import router from './router'
sync(store,router)
this.$store.state.route.path //current path (string)
this.$store.state.route.params //current params (object)
this.$store.state.route.query //current query (object)