关于vue.js:vueVuex状态管理模式

41次阅读

共计 6110 个字符,预计需要花费 16 分钟才能阅读完成。

Vuex 状态管理模式

多个组件依赖或批改同一个状态 – 共享
应用 Vue.observable 能够实现一个轻量型的状态治理

  1. 根底
  2. Modules

1 根底

  1. 根本构造与应用
  2. State
  3. Mutations
  4. Actions
  5. Gtters
  6. map

1.1 根本构造与应用

结构图

装置 Vuex

npm install vuex --save

store.js 文件

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
    mutations: {increment() {this.state.count++},
        decrement() {this.state.count--}
    },
    state: {count: 0}
})

组件一

<template>
  <div>
    <button @click="add">+</button>
    <span>{{num}}</span>
  </div>
</template>

<script>
import {store} from "../store";
export default {
  store: store,
  computed: {num() {return store.state.count;},
  },
  methods: {add() {store.commit("increment");
    },
  },
};
</script>

<style>
</style>
//main.js
import {store} from './store'
new Vue({
  store,
  render: h => h(App),
}).$mount('#app')
// 组件二
dec() {this.$store.commit("decrement");
},

两个组件能够操作同一个值

  • 在 store 文件中引入 Vue 以及 Vuex
  • Vue.use(Vuex),new Vuex.Store({})
  • 在组件中引入 store 并注册,能够间接应用 store
  • 根实例 中引入并注册 store,子组件能够通过 vm.$store 来拜访与批改数据

1.1 State

存储 状态
每个数据作为对象属性供各个组件拜访
通常会应用 计算属性 让状态能在组件中应用,当状态变动时会从新计算

1.2 Mutations

更改 Vuex 的 store 中状态的惟一办法是提交 mutation

  • mutation 中的回调函数接管 state 作为 第一个参数

    mutations: {increment (state) {state.count++}
    }
  • 通过 store.commit 来申明应用哪个回调解决数据,能够传递 额定的参数

    mutations:{increment(state,n){state.count +=n}
    }
    // 提交
    store.commit('increment',10)

    参数为一个对象

    mutations: {increment (state, payload) {state.count += payload.amount}
    }
    // 提交
    store.commit('increment',{amount:10})
  • 对象模式的提交

    // 解决的回调与参数时对象的雷同
    mutations: {increment (state, payload) {state.count += payload.amount}
    }
    // 整体提交一个对象
    store.commit({type:'increment',amount:10})
  • 如果须要增加状态,能够应用 Vue.set(obj,key,val),或者应用 扩大符 解构赋值

    // 提交增加状态
    addOne() {store.commit("addState", { name: "张三"});
    },
    // 增加状态的回调
    addState(state, obj) {const keys = Object.keys(obj)
      Vue.set(state, keys[0], obj[keys[0]])
    }

Mutation 必须是 同步函数,异步操作时不能断定是哪个操作在扭转状态

1.3 Actions

相似于 mutation,不同如下:

  • 提交的是mutation,不间接更改状态
  • 能够蕴含 异步 操作

store

actions: {getData(context, param) {const oneData = [param, '数据 1', '数据 2']
        context.commit('GETDATA', oneData)
    }
},
mutations: {GETDATA(state, data) {Vue.set(state, 'myData', data)
    },
},
state: {myData: [],
}

组件

<template>
  <div>
    <button @click="getItem"> 申请数据 </button><br />
    <span v-for="(item, index) in myData" :key="index">{{item}}</span>
  </div>
</template>

<script>
export default {
  computed: {myData() {return this.$store.state.myData;},
  },
  methods: {getItem() {this.$store.dispatch("getData", "申请");
    },
  },
};
</script>
  • Action 的回调函数接管一个与 store 实例具备雷同属性和办法的 context 对象作为 第一个参数

    context !== this,context 并 不是 store 实例自身,mutation 的 state 参数则是 store 实例上的实在的属性
    在 action 中次要应用 contextcommit办法去提交 mutation,所以能够应用 解构赋值 的形式简化参数,能够读 state 中的数据

    actions:{getData({commit},param){commit('GETDATA',parm)
        }
    }
  • Action 通过 store.dispatch 进行散发,如果回调函数返回一个 Promise,能够在散发的前面进行 链式操作 或者在其余 action 中进行链式操作

    actions:{actionA({commit}){return new Promise(async (resolve,reject)=>{await delay();
            commit('mutation1');
            resolve()})
      },
      actionB({dispatch,commit}){return dispatch('actionA').then(()=>{commit('mutation2')
          })
      }
    }
  • Action 中能够 异步 申请与操作,在不同的异步阶段 提交 mutation,能够利用 async/await 组合 action

1.4 Getters

相似与 计算属性
在应用 state 中数据的同时,可能还须要由 state 派生出的一些状态,这时能够在组件内应用计算属性对 state 进行操作
然而当多个组件须要同样的派生状态,局部组件须要原 state 时,在每个组件内都应用计算属性显然很麻烦
getter 能够将 state 中的数据计算后供组件拜访

//store
state: {
    user: [{ name: '张三', age: 18},
        {name: '李四', age: 15},
        {name: '王二', age: 21},
        {name: '麻子', age: 17},
    ]
},
getters: {adult({ user}) {
        return user.filter(item => {return item.age >= 18})
    }
}
// 组件内
computed: {adultUser() {return this.$store.getters.adult;},
},
  • getters 中的回调第一个参数state,第二个参数getters
  • 能够让 getter返回一个函数 ,这样能够向 getter 中传递数据,配合数组的 find 办法,能够对 store 中的数据进行 查问

1.5 map

辅助函数

  1. mapState
  2. mapGetters
  3. mapMutations
  4. mapActions

1.5.1 mapState

当一个组件须要 多个 状态时,频繁应用计算属性让代码很臃肿,应用辅助函数能够 简化操作

//store
state: {
  a: 1,
  b: 2
},
// 组件
<template>
  <div>
    <span>{{a}}{{b}}</span>
  </div>
</template>

<script>
import {mapState} from "vuex";
export default {
  computed: {
    // 数组参数
    ...mapState(["a", "b"]),
  },
};
</script>

引入 mapState 函数,参数为数组模式,然而 不能改名 ,容易与 data 中的数据发生冲突
mapState 函数返回一个 对象,应用开展运算符,能够一一混入到计算属性中

// 对象参数
computed: {
  ...mapState({
    a: "a",
    bar: "b",
  }),
},

1.5.2 mapGetters

与 mapState 函数相似

  • 在组件中引入 mapGetters 函数
  • 两种传参形式
  • 应用扩大运算符将 getter 混入 computed 对象中
  • 相当于计算属性的后果在组件中应用

1.5.3 mapMutations

将组将中的 methods 映射为 store.commit 调用

//store
state: {count: 0},
mutations: {increment(state, param) {state.count += param}
}
// 组件
<template>
  <div>
    <button @click="add(10)"> 加 10</button>
    <span>{{num}}</span>
  </div>
</template>

<script>
import {mapMutations} from "vuex";
import {mapState} from "vuex";
export default {
  computed: {
    ...mapState({num: "count",}),
  },
  methods: {
    ...mapMutations({add: "increment",}),
  },
};
</script>
  • 在组件中引入 mapMutations 函数
  • 两种传递参数的形式
  • 扩大运算符将返回的对象混入到 methods
  • 相当于在 methods 中注册的办法,调用时能够 传递参数,作为回调函数的第二个参数

1.5.4 mapActions

与 mapMutations 相似
最终能够在组件中调用,能够应用 this 灵便的调用

2 Module

当状态较多时,store 对象就会变得越来越臃肿
Vuex 反对将 store 对象宰割成模块。每个模块领有本人的 state、mutation、action、getter 甚至是嵌套子模块

2.1 模块化的导入和导出

目录构造示例

└── store
    ├── index.js          # 咱们组装模块并导出 store 的中央
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── topics.js       # 购物车模块
        └── comments.js   # 产品模块
// 模块 1
export const Topics = {
    state: {
        backTopic: '举荐',
        userTopic: '自定义'
    },
    mutations: {modify(state, param) {state.userTopic = param}
    }
}
// 模块 2 有同名的 mutation
...
//mutathions.js 有一个同名的办法
...
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
import {Topics} from './modules/topics'
import {Comments} from './modules/comments'
import {mutations} from './mutations'

Vue.use(Vuex)

export const store = new Vuex.Store({
    state: {root: '根状态'},
    mutations,
    modules: {
        Topics,
        Comments
    }
})

子模块引入在 modules 对象中,无需改名能够应用简写模式
这样能够分模块操作,根 state 中会依据引入的模块混入 子 state 对象
如果在组件中间接提交 mutation,同名的 mutation会同时开始操作

  • 在模块导出时增加namespaced:true,能够辨别不同模块的同名操作

    export const Topics = {
      namespaced: true,
      state: {
          backTopic: '举荐',
          userTopic: '自定义'
      },
      mutations: {modify(state, param) {state.userTopic = param}
      }
    }
  • 模块中的 action 的 context 中能够接管到跟状态 rootState
  • 模块中的 getter 的参数:state getters rootState rootGetters

2.2 在组件中散发与提交

2.2.1 通过 store 间接拜访

// 读取 state
computed: {userTopics() {return this.$store.state.Topics.userTopic;},
}
// 提交 mutation
this.$store.commit("Topics/modify", "批改");

应用命名空间时,须要增加 门路 能力提交 mutation,action 亦是如此

2.2.1 应用辅助函数

computed: {
  ...mapState({a: (state) => state.Topics.userTopic,
  }),
},
methods: {
  ...mapMutations({modiT: "Topics/modify",}),
},

对某一个模块的屡次援用,能够进行简化

computed: {
  ...mapState("Topics", {
    a: "userTopic",
    b: "backTopic",
  }),
},
methods: {
  ...mapMutations("Topics", {modiT: "modify",}),
},

createNamespacedHelpers函数

import {createNamespacedHelpers} from 'vuex'

const {mapState, mapMutations} = createNamespacedHelpers('Topics')

此时生成的辅助函数会有一个自定义的门路,能够像个别状况下应用

其余注意事项

  • 在模块中注册全局 action

    将回调函数写成对象模式,增加属性 root:true,回调写放在handler 办法中

  • 动静注册模块

    创立 store 后应用 registerModule 函数

    // 注册模块 `myModule`
    store.registerModule('myModule', {// ...})
    // 注册嵌套模块 `nested/myModule`
    store.registerModule(['nested', 'myModule'], {// ...})

正文完
 0