该文章描述的是利用脚手架自动搭建的vuex目录结构,再加上自己的进一步封装而写成的。
vuex是vue全家桶自带的一个模块,在根目录的store/index.js中进行配置,在main.js中使用
import store from "./store"
*(默认选中index.js文件)导入即可
store/index.js中的配置(默认)
import Vue from 'vue';
import Vuex from 'vuex';
//挂载vuex
Vue.use(Vuex);
//创建store实例
const store = new Vuex.Store({
state:{}, //相当于一个存储空间
getters:{}, //state的计算数据 实现数据过滤的作用(get)
mutations:{},//设置state中的数据(set)
actions:{}, //可以发送异步请求
modules:{}, //拆分存储空间模块化
plugins:{}, //拓展vuex功能
})
//导出store对象
export default store;
进一步封装(拆分创建store实例时的配置项)
目录树
+ store
+ index.js
+ state.js
+ getters.js
+ mutations.js
+ actions.js
+ modules
+ user.js
+ plugins
// 这个配置文件是为了实现vuex的数据持久化
+ saveInLocal.js
index.js中代码编写
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
import m_user from './modules/user.js'
import saveInLocal from './plugins/saveInLocal'
Vue.use(Vuex);
/*
这里涉及一个代码风格的设计思想,将目录名称与要设置的对象名称命名为一样的名称,可以利用es6语法,实现快速导入。
*/
const store = new Vuex.Store({
state, //也就是 state:state
getters,
mutations,
actions
modules:{
m_user
},
plugins:[saveInLocal]
})
export default store;
state.js中代码编写
export default {
code:"qq",
name:"张三"
}
getters.js中代码编写
export default {
_getName:(state)=>{
return "这是通过getters添加的"+state.name;
},
_getInfo:(state)=>{
return `${state.name}-${state.code}`;
}
}
mutations.js中代码编写
mutations中不能有异步方法
export default {
SET_NAME:(state,param)=>{
state.name = param
}
}
actions.js中代码编写
axtions执行逻辑:actions->mutations->state->视图
//封装一下定时器promise
function delay(time){
return new Promise((resolve,reject)=>{
//起定时器
setTimeout(resolve,time)
})
}
export default {
//5s后修改名字
/*
setNameAfter5:(store,param)=>{
setTimeout({
this.store.commit('SET_NAME',param)
},5000)
}
*/
//上面那种普通的办法太过繁琐,使用promise封装
/*
setNameAfter5:(store,param)=>{
delay(5000).then(()=>{
this.store.commit('SET_TIME',param)
})
}
*/
//这个还是有点麻烦,使用promise的async和await修饰词
/*
setNameAfter5:async (store,param)=>{
await delay(5000);
this.store.commit('SET_TIME',param)
}
*/
//上面的改变还是不够精简,利用es6语法(解构赋值、函数简写)
async setNameAfter5({commit},param){
await delay(5000);
commit('SET_TIME',param)
}
//NICE~
}
modules/user.js中代码编写
//封装定时器
function delay(time){
return new Promise((resolve,reject)=>{
setTimeout(resolve,time)
})
}
export default {
state:{
userName:"李四"
},
getters:{
getUserName:(state)=>{
return "我是" + state.userName;
}
},
mutations:{
SET_NAME:(state,param)=>{
return state.userName = "hahah"
}
},
actions:{
async setUsernameAfter5({commit},param){
await delay(5000);
commit('SET_NAME',param);
}
}
}
vue页面中对state中存储内容的读取(state,getters)操作(computed)
<template>
{{ getName }}
{{ _getName }}
{{userName}}
{{getUserName}}
template>
<script>
import { mapState,mapGetters } from 'vuex' //使用vuex自带的方法
export default{
//state中存储的值需要在computed中获取
//getters中的函数也只能在computed中调用
computed:{
//state*******
//方法三:这种方法是可以在return前做一个数据处理
...mapState({
getName:(state)=>{
//做个数据处理再返回
return state.name + '哈哈哈哈'
},
code:(state)=>state.code
}),
//方法二:mapState(需要获取state存储空间中值的数组列表),它的返回值是一个函数数组,而computed就需要一个个函数,所以在此将返回的数组展开即可
...mapState(['name']),//同样能拿到name的值
getName(){
//方法一:使用默认方法拿取name值
let name = this.$store.state.name;
return name;
},
//getters*******
//方法一:使用默认方法调用getName
_getName(){
return this.$store.getters._getName;
},
//方法二:使用vuex的map方法
...mapGetters(['_getInfo','_getName']),
//方法三:使用对象(但getters本身就是计算后属性,这个方法一般不使用)
...mapGetters({
_getInfo:(state)=>{//做数据处理}
}),
/***********子模块***********/
//state******
userName(){
//方法一:使用默认方法拿取username值
this.$store.state.m_user.userName;
},
//方法二:通过mapState
...mapState('m_user',['userName'])
//方法三:对象
...mapState('m_user',{
userName:(state)=>{
return state.userName + '可以进行修改'
}
}),
//getters******
getUserName(){
//方法一:使用默认方法
return this.$store.getters['m_user/getUserName']
}
//方法二:使用mapGetters
...mapGetters('m_user',['getUserName'])
}
}
script>
vue页面对state中存储的值进行修改(mutations\actions)操作(methods)
在严格模式下,不支持直接修改state中的值
//index.js中
const store = new Vuex.Store({
strict : true //严格模式开启
//其它忽略不写
})
页面代码
<template>
<view>{{ name }}view>
<view>{{ userName }}view>
<button @click="changeName">修改name值button>
<button @click="changeNameAsync">5s后修改name的值button>
<button @click="changeUsername">修改userName的值button>
<button @click="changeUsernameAsync">5s后修改userName的值button>
template>
<script>
import { mapState,mapMutations,mapActions } from 'vuex'
export default {
computed:{
...mapState(['name']), //拿到name值
...mapState('m_user',['userName'])
}
methods:{
//默认根模块
//mutations(同步修改)
...mapMutation(['_SETNAME']),
changeName(){
//方法一:直接通过$store修改(vuex不推荐直接修改)
this.$store.state.name = "哈哈哈哈"
//方法二:用过mutation进行修改
this._SETNAME('哈哈哈哈');
}
//actions(异步修改)
` `...mapActions(['setNameAfter5']),
//5s后修改名字
changeNameAsync(){
//方法一:使用默认store的dispatch进行分发
this.$store.dispatch('setNameAfter5',"dispatch")
//方法二:通过mapAction进行修改
this.setNameAfter5('名字');
}
//子模块m_user
...mapMutations('m_user',['SET_NAME']),
//mutations(同步修改)
changeUsername(){
//方法一:直接修改
this.$store.state.m_user.userName = "修改啦"
//方法二:使用mapMutations
this.SET_NAME('修改啦')
},
//actions异步修改
...map('m_user',['setUsernameAfter5']),
changeUsernameAsync(){
this.$store.dispatch('setUsernameAfter5','5s后修改')
}
}
}
script>
vuex配置项之持久化
saveInLocal.js中代码的编写
function saveInLocal(store){
console.log(store,'初始化state数据')
if(localStorage.state){
store.replaceState(JSON.parse(localStorage.state));
}
store.subscribe((mutations,state)=>{
console.log('mutation被调用,就执行')
// 将state存储到localStorage中
localStorage.state = JSON.stringify(state);
})
}
export default saveInLocal