文章目录
组件间非完全独立,在很多情况下需进行数据交互,当多个组件共享一个数据时,该数据的定义、改变,通常定义在他们的父组件中。由于存在多组件嵌套、兄弟间通信,操作相对繁琐。故对组件的共享状态抽取,全局单例,进行集中式管理。
Vuex:对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)
流程
将Vue组件中的事件请求分发给actions对象中的事件回调函数,以commit提交的方式来触发mutations对象中state更新方法的调用,进而更新状态对象state,再以直接或计算属性(getters中定义)的方式映射回Vue视图
Actions对象中可包含异步代码(定时器, ajax)
应用
main.js:入口JS
import Vue from 'vue'
import APP from "./App"
import "./base.css" //全局的样式
import store from "./store" //自动匹配下面的index.js
// 创建vm
new Vue({
el: '#app',
components: {
App}, // 映射组件标签
template: '<App/>', // 指定需要渲染到页面的模板
store // 所有的组件对象都多了一个属性: $store(值就是store对象)
})
创建vm方式2:
new Vue({
el: "#app",
render: h => h(APP), // =>函数的参数是 h(也是函数) 返回 h(APP)的结果
store
});
index.js:vuex核心管理模块store对象
import Vue from "vue"
import Vuex from "vuex"
import actions from "./actions"
import mutations from "./mutations"
import state from "./state"
import getters from "./getters"
Vue.use(Vuex); //引入插件
export default new Vuex.Store({
//export是对外暴露
state,
getters,
actions,
mutations
})
state.js:状态对象模块
export default {
items:[]
}
App.vue中在mounted中分发本地保存数据请求事件
mounted() {
this.$store.dispatch("requestItems");
//名称requestItems和参数决定actions对象中对应的事件回调
}
actions.js:包含n个用于间接更新状态的方法的对象模块
import {
ADD_ITEM,DEL_ITEM,SEL_ALL,DEL_COMPLETED,REQUEST_ITEMS} from "./mutation-types"
export default {
requestItems({
commit}) {
commit(REQUEST_ITEMS);//该名称常量REQUEST_ITEMS定义是为保持与mutations方法名一致
},
delItem({
commit},index) {
commit(DEL_ITEM, {
index}); //参数需要以对象形式进行传递 {参数}
}
。。。
}
mutations.js:包含n个用于直接更新状态的方法的对象模块
import {
ADD_ITEM,DEL_ITEM,SEL_ALL,DEL_COMPLETED,REQUEST_ITEMS} from "./mutation-types"
import storageUtil from "../utils/storageUtil"
export default {
[REQUEST_ITEMS](state) {
// []的意义在于方法名REQUEST_ITEMS对应的变量request_items
state.items = storageUtil.readItems();
},
[SEL_ALL](state, {
value}) {
//这里的value为true/false
state.items.forEach(item => item.state=value)
}
。。。
}
mutation-types.js:包含n个mutation名称常量
export const REQUEST_ITEMS = "request_items"; //注意需要export
export const ADD_ITEM = "add_item";
export const DEL_ITEM = "del_item";
。。。
getters.js:包含n个基于state的getter计算属性方法的对象模块
export default {
completedSize(state) {
const items = state.items;
return items.reduce((preTotal,item)=>preTotal+(item.state?1:0),0)
},
isAllState(state,getters) {
//可以传参state,getters等
return getters.completedSize === state.items.length && state.items.length > 0;
}
}
TodoFoot.vue
<label>
<input type="checkbox" v-model="isAllState"/> //配合get set双向绑定
</label>
<span>已选中{
{
completedSize}}/ 全部{
{
items.length}}</span>
。。。
import {
mapState,mapGetters,mapActions} from "vuex"
。。。
computed: {
...mapState(["items"]), //计算属性作为组件本身的属性,可以监视其变化
...mapGetters(["completedSize"]) //简化调用,completedSize就好,要不太复杂:this.$store.getters.completedSize
//
},
//methods:{ //"increment"即用increment调用对应actions中的increment方法
//...mapActions(["increment","decrement","oddIncrement","synIncrement"])
//},
isAllState: {
get() {
return this.$store.getters.isAllState;
},
set(value) {
// this.selAll(value);
this.$store.dispatch("selAll", value);
}
}
},
watch:{
//深度监视
items:{
//computed中的...mapState(["items"])引入该属性
deep:true,
handler: storageUtil.saveItems //
}
}
storageUtil.js
/*
向local中存储数据的工具模块
1. 向外暴露一个函数(功能) 只有一个功能需要暴露
export function xxx() {
}
2. 向外暴露一个对象(包含多个功能) 有多个功能需要暴露
*/
const ITEMS_KEY = "Items_key"; //为维持存取键值一致
export default {
saveItems(Items) {
window.localStorage.setItem(ITEMS_KEY, JSON.stringify(Items));
},
readItems() {
return JSON.parse(window.localStorage.getItem(ITEMS_KEY) || "[]");
}
}