vuex 状态管理
状态管理(集中式存储管理应用的所有组件的状态), 它最大的特点是响应式。
Vuex有哪些属性
state: {}, ==> 就是来放入数据的[类似于组件中的data]
getters:{}, ==> 获取data中的数据,类似计算器属性
mutations: {}, ==> 用来修改 data中的数据
actions: {}, ==> 用来发异步请求, 吩咐mutations去更新数据
modules: {}, ==>模块化数据仓库
使用步骤
安装:
yarn add vuex // 安装最新的
yarn add vuex@3 // 指定版本安装
注意根据vue版本来选择vuex的版本, 如果vue是版本2 , vuex 选择版本3
安装vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 实例化一个vuex实例化对象
var store = new Vuex.Store({
state:{
count:1,
userInfo:{
role:['admin'],
menus:['/home'],
username:'alice'
}
}
})
export default store;
在vue实例上挂载
import store from './store/index'
var vm = new Vue({
// 会自动将store对象注入到所有子组件中
// 组件中可以通过this.$store获取到
store:store, // 挂载store
render: h => h(App),
router:router
}).$mount('#app')
vuex 有如下五个核心模块:
state:
- 用于存放组件间互相通信的属性值。
- 原则上 state 中的属性只能在各个组件之间使用,而不能修改,如果要修改需要在 mutations 中修改
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 实例化一个vuex实例化对象
var store = new Vuex.Store({
state:{
count:1,
userInfo:{
role:['admin'],
menus:['/home'],
username:'alice'
}
}
})
export default store;
在组件中获取数据
{{ $store.state.userInfo }}
或者通过mapState 获取
import {mapState} from 'vuex'
....
computed:{
...mapState(['count','todolist'])
}
....
getters
- 这里也是一些函数,类似于组件中的计算属性
- 可以处理一些通用且复杂的逻辑, 实际使用比较少
// 实例化一个vuex实例化对象
var store = new Vuex.Store({
....
getters:{
todoFinished(state){
var finishedTodo = state.todolist.filter((item)=>{
return item.finished
})
return finishedTodo;
}
}
})
mutations
-
这里存放的都是一些函数,用于修改 state 中的属性值
-
这里的函数中只接收两个参数:state 和 options
-
这里面的函数必须都是同步的
-
如果某组件中需要修改 state 中的属性值,则需在该组件中用this.$store.commit (’ 方法名 ', 参数) 的方式来调用,即需要用 commit 方法来 调用 mutations 中的函数
-
通过 commit 触发
//定义 export default new Vuex.Store({ mutations:{ changeUserInfo(state,name){ state.userinfo.name = name; } } }) //使用 this.$store.commit("changeUserInfo", "Yannis") this.$store.commit({ type:'changeUserInfo', data:'Yannis' })
actions
- 这里存放的也都是一些函数,这里的函数可以是异步的
- 这里的函数也是接收两个参数:store 和 options
- 如果这里的函数想要修改 state 中的值,还是得通过调用 mutations 中的方法来实现
- 如果想要在组件中调用这里的函数,则需要用 dispatch 方法调用:this.$store.dispatch (’ 方法名 ', options)
- 通过 dispatch 触发
modules
- 用于划分模块
- 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象显得会相当臃肿
- 为了解决上面的问题,Vuex 允许将 store 分割成模块。每个模块拥有自己的 state、mutation、action、getter 甚至是嵌套子模块
- 如果模块中的 mutations 或 actions 重复,则两个重复的方法都会执行
- 如果想区分模块中重复的 mutations 或 actions,则可以在模块中加一个属性:namespaced:true 即可,调用时需要指定模块名,例如:this.$store.commit (’ 模块名 / 方法名 ')
Vuex持久化存储
1 使用插件vuex-persistedstate
1.1 安装
yarn add vuex-persistedstate // 或 npm install --save vuex-persistedstate
1.2 配置
import Vuex from "vuex";
// 引入插件
import createPersistedState from "vuex-persistedstate";
Vue.use(Vuex);
const store = new Vuex.Store({
state,
mutations,
actions,
/* vuex数据持久化配置 */
plugins: [
createPersistedState({
// 存储方式:localStorage、sessionStorage、cookies
storage: window.sessionStorage,
// 存储的 key 的key值
key: "store",
render(state) {
// 要存储的数据:本项目采用es6扩展运算符的方式存储了state中所有的数据
return { ...state };
}
})
]
});
export default store;
2. 方法是 vuex-along
(1)安装 vuex-along
npm install vuex-along --save
(2)在store文件夹里的index.js中引入vuex-along并配置相关代码
import Vue from 'vue'
import Vuex from 'vuex'
import indexOne from "./modules/indexOne"
import VueXAlong from 'vuex-along'
Vue.use(Vuex)
const store=new Vuex.Store({
strict: false,
modules:{
indexOne
},
plugins: [VueXAlong({
name: 'along', //存放在localStroage或者sessionStroage 中的名字
local: false, //是否存放在local中 false 不存放 如果存放按照下面session的配置配
session: { list: [], isFilter: true }
//如果值不为false 那么可以传递对象 其中 当isFilter设置为true时, list 数组中的值就会被过滤调,这些值不会存放在seesion或者local中
})]
})
export default store;
3. vuex-persist
(1)安装 vuex-persist
npm install --save vuex-persist
or
yarn add vuex-persist
(2)在store文件夹里的index.js中引入vuex-persist并配置相关代码
import Vue from 'vue'
import Vuex from 'vuex'
import indexOne from "./modules/indexOne"
import VuexPersistence from 'vuex-persist'
Vue.use(Vuex)
const vuexLocal = new VuexPersistence({
storage: window.localStorage
})
const store = new Vuex.Store({
strict: false,
modules:{
indexOne,
},
plugins: [vuexLocal.plugin]
})
export default store;
结语:
其实解决此问题的方法有很多,基本上都是要借助于localStorage或者sessionStroage来存放**。
基于 vuex 的原理模拟部分 Vuex 源码
let Vue = null;
function install(_Vue){
Vue = _Vue;
Vue.mixin({
beforeCreate(){
if(this.$options.store){
//说明是根实例
this$store = this.$options.$store
}else if(this.$parent){
//有$parent属性,说明这个组件是根组件的后代组件
this.$store = this.$parent.$store
}
}
});
}
class Store{
constructor(options){
//this.state = options.state;//没有响应式
let vm = new Vue({
data:{
state: options.state
}
});
this.state = vm.state;
this.mutations = {};
let mutations = options.mutations || {};
Object.keys(mutations).forEach(key => {
this.mutations[key] = (option) => {
mutations[key].call(this,this.state, option);
}
});
this.actions = {};
let actions = options.actions || {};
Object.keys(actions).forEach(key => {
this.actions[key] = (option) => {
actions[key].call(this, this.store, option);
}
});
this.getters = {};
let getters = options.getters || {};
Object.keys(getters ).forEach(key => {
Object.defineProperty(this.getters, key, {
get:() => {
return getters[key].call(this, this.state);
}
})
});
this.commit = (type, option) => {
this.mutations[type](option);
}
this.dispatch = (type, option) => {
this.actions[type](option);
}
}
/*
* commit 和 dispatch应该是stote私有的
commit(type, option){
this.mutations[type](option );
}
dispatch(type, option){
this.actions[type](option);
}
*/
}
//辅助函数
export function mapState(arr){
let obj = {};
arr.forEach(key => {
obj[key] = function(){
return this.$store.state[key]
}
});
return obj;
}
export function mapMutation(arr){
let obj = {};
arr.forEach(key => {
obj[key] = function(option){
return this.$store.commit(key, option)
}
});
return obj;
}
export default {
install,
Store
}