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)
复制代码
来源: https://juejin.im/post/5b52bb6d5188251b3e645b1e