目录
2、mutations.js :保存所有方法,用来改变state的数据
3、actions.js :暴露给用户使用,借此触发mutations中的方法,保存数据(可执行异步操作)
4、index.js:引入相应模块,暴露出store,供vue注册后全局使用
vuex安装
npm install --save vuex
安装成功后,可在package.json中看到安装的版本
vuex是使用vue中必不可少的一部分,基于父子、兄弟组件,我们传值可能会很方便,但是如果是没有关联的组件之间要使用同一组数据,就显得很无能为力,那么vuex就很好的解决了我们这种问题,它相当于一个公共仓库,保存着所有组件都能共用的数据。
那么,我们一起来看看vue项目怎么使用它吧。(如果你对vuex有一定了解,不是刚接触的小白,请忽略第一步,直接查看第二步)
一、适合初学者使用,保存数据以及获取数据
1、在store文件夹,新建个index.js文件
(命名看个人习惯,如果没有该文件夹,可以新建一个,当然也可以不建文件夹,直接新建个js文件也是可以的)
在新建的js文件中写入如下代码:
import Vue from "vue" import Vuex from "vuex" Vue.use(Vuex); export default new Vuex.Store({ state:{ pathName: "", currDbSource: {}, currJobData: {}, DbSource: [] }, mutations:{ // 保存当前菜单栏的路径 savePath(state,pathName){ state.pathName = pathName; }, // 保存当前点击的数据源 saveCurrDbSource(state,currDbSource){ state.currDbSource = currDbSource; }, // 保存当前点击的元数据 saveCurrJobData(state,currJobData){ state.currJobData = currJobData; }, // 保存所有数据源 saveDbSource(state,DbSource){ state.DbSource = DbSource; } } })
这里解释一下各个代码段的作用:state是自定义的一些变量,需要用来保存数据,mutations是用来触发事件,相当于方法,用户需要通过触发这个方法,借此来保存数据,参数的话,第二个参数就是用户传入的值,然后在方法中赋值给state中的变量
2、main.js引用:(注意路径即可)
//引入vuex-store import store from '../store/index' new Vue({ el:'#app', router, store, render:h=>h(App), methods:{ click(){ //点击按钮进行一些操作,然后保存数据 this.$store.commit('saveCurrDbSource',this.db) } }, computed:{ a:this.$store.state.currDbSource, } })
3、保存数据:(场景举例:当我点击按钮后,我需要把当前的数据保存到vuex中,然后跳转到别的路由,然后使用这些数据)
methods:{ click(){ // 点击按钮进行一些操作,然后保存数据 this.$store.commit('saveCurrDbSource',this.db) } }
这里的第一个参数是要触发的方法,也就是上面mutations中的方法,第二个参数是你要传递的数据
4、获取变量:(当数据初始获取不到时,可以使用计算属性用来获取)
this.$store.state.变量名 // 例如 this.$store.state.currDbSource
这样其他组件就可以共用这个保存起来的数据了,也能进行相应的修改
二、模块化(适合有部分基础的人)
当然,上述方法中我们把所有东西都写在一个文件中了,这样数据多的时候,耦合度太高,也不便于维护,而且mutations也不能解决异步问题,这里就介绍另一种方式以及actions
actions:看过官网介绍的人都知道,这是间接触发mutations方法的一种 " 中间商 ",而且它可以执行异步操作,避免用户去直接操作state
1、state.js :保存所有数据,以对象的方式导出
export default { pathName: '', // 路由 currDbSource: {}, // 当前数据源 currJobData: {}, // 当前元数据 DbSource: [], // 所有数据源,供元数据界面下拉列表使用 selectJobMeta: {}, // 当前选择的元数据(搜索后点击的单条数据) specialSubject: [], // 专题数据(多条) duplicateJobMeta: {}, // 复制的数据 };
2、mutations.js :保存所有方法,用来改变state的数据
// 保存当前菜单栏的路径 export const savePath = (state, pathName) => { state.pathName = pathName; }; // 保存当前点击的数据源 export const saveCurrDbSource = (state, currDbSource) => { state.currDbSource = currDbSource; }; // 保存当前点击的元数据 export const saveCurrJobData = (state, currJobData) => { state.currJobData = null; state.currJobData = currJobData; }; // 保存所有数据源 export const saveDbSource = (state, DbSource) => { state.DbSource = DbSource; }; // 保存搜索后选择的那一条元数据 export const saveSelectJobMeta = (state, selectJobMeta) => { state.selectJobMeta = selectJobMeta; }; // 保存搜索的那一类专题 export const saveSpecialSubject = (state, specialSubject) => { state.specialSubject = specialSubject; state.selectJobMeta = {}; }; // 保存复制的元数据(名称为空) export const saveDuplicateJobMeta = (state, duplicateJobMeta) => { state.duplicateJobMeta = duplicateJobMeta; };
3、actions.js :暴露给用户使用,借此触发mutations中的方法,保存数据(可执行异步操作)
// 触发保存菜单栏的路径方法 export const savePath = ({ commit }, payload) => { commit('savePath', payload); }; // 触发获取当前点击的数据源方法 export const saveCurrDbSource = ({ commit }, payload) => { commit('saveCurrDbSource', payload); }; // 触发获取当前点击的元数据方法 export const saveCurrJobData = ({ commit }, payload) => { commit('saveCurrJobData', payload); }; // 触发获取所有数据源方法 export const saveDbSource = ({ commit }, payload) => { commit('saveDbSource', payload); }; // 触发保存搜索后选择单条元数据方法 export const saveSelectJobMeta = ({ commit }, payload) => { commit('saveSelectJobMeta', payload); }; // 触发保存搜索专题数据方法 export const saveSpecialSubject = ({ commit }, payload) => { commit('saveSpecialSubject', payload); }; // 触发保存复制元数据方法 export const saveDuplicateJobMeta = ({ commit }, payload) => { commit('saveDuplicateJobMeta', payload); };
这里有2种方式:
// 方法一: export const saveDbSource = (context, payload) => { context.commit('saveDbSource', payload); }; // 方法二: export const saveDbSource = ({ commit }, payload) => { commit('saveDbSource', payload); };
第一种是通过 context上下文用来触发事件,一种是直接通过commit,为了保存数据,都需要加第二个参数payload,不然保存到vuex的数据就是空值
4、index.js:引入相应模块,暴露出store,供vue注册后全局使用
import Vue from 'vue'; import Vuex from 'vuex'; import state from './state'; import * as actions from './actions'; import * as mutations from './mutations'; Vue.use(Vuex); export default new Vuex.Store({ state, actions, mutations });
5、main.js中引入index.js
// 引入vuex-store import store from './store/index'; new Vue({ el: '#app', router, store, render: h => h(App) });
6、保存数据
这里也有2种保存数据的方法,第一种就是直接操作方法,通过disptach派发给actions,让actions去触发
第二种就是通过在methods中添加映射关系,数组方式,意味着我们可以在数组中写多个方法(这里数组中的每一个方法名是actions.js文件中所定义的方法名),然后在需要使用的地方直接this.方法名即可。当然,也可以直接绑定给html中的某个事件。
值的注意的是,避免和methods中自己定义的其他方法的名字冲突
import { mapActions } from 'vuex'; // 2种方式 // 方法一(dispatch) this.$store.dispatch('saveDbSource', this.DbSource); // 方法二(映射) // 1、通过methods方法添加映射关系 methods: { ...mapActions(['saveDbSource']) } // 2、使用 this.saveDbSource
7、获取数据
import { mapState } from 'vuex'; computed: { ...mapState(['DbSource']), // 推荐写法如下: //...mapState({ // DbSource: state => state.DbSource, // phoneMap: state => state.richCommunicationSuite.phoneMap, // 模块化写法 //}), }, watch: { DbSource(currVal) { // 监听mapState中的变量,当数据变化(有值、值改变等), // 保证能拿到完整的数据,不至于存在初始化没有数据的问题,然后可以赋给本组件data中的变量 this.currVal = currVal; } }
通过计算属性,当数据发生改变,我们可以保证拿到的是响应过后的数据,也是数组形式,意味着我们可以拿到多组数据,这里数组中的数据也是state.js中定义的变量(当然,更推荐使用我注释的那段代码,那种写法可以应对当state中存在多模块的情况,比如state.a.xxx,state.b.xxx,其中a和b都是两个模块,各自有对应的数据要存储,也可以自定义我们前面的名字来避免和data中数据重名的情况)
使用的时候,可以直接通过this.变量名拿到,例如本例中的 this.DbSource,我们可以把它赋给我们自定义的变量,也可以直接使用
值的注意的是,避免和data中自己定义的其他变量的名字冲突
至此,我们就完成了vuex的保存以及获取数据,希望对你有所帮助。
当然,我们需要把一vuex中的一组数据过滤,其他组件都共用过滤后的数据,这种情况大家可能会用到getters,这里我就不多赘述了,有兴趣的小伙伴可以自己了解一下。
附上vuex的运行过程,官网的图片:组件派发任务到actions,actions触发mutations中的方法,然后mutations来改变state中的数据,数据变更后响应推送给组件,组件重新渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="../js/vuex.js"></script>
</head>
<body>
<div id="app">
{{msg}}
<hr>
{{$store.state.storeMsg}}-----{{$store.state.name}}
<hr>
{{$store.getters.nameUpper}}
<hr>
<!-- commit 提交突变 -->
<button @click="$store.commit('changName','lisi')">提交突变</button>
<!-- dispatch 动作分发-->
<hr>
<button @click="$store.dispatch('getName','lisi33333')">动作分发</button>
<hr>
{{storeMsg}}----{{name}} ----{{nameUpper}}
<hr>
<button @click="changName('lisi')">提交突变</button>
<!-- dispatch 动作分发-->
<hr>
<button @click="getName('lisi33333')">动作分发</button>
</div>
<script>
// import {mapActions,mapMutations} from 'vuex'
let {mapActions,mapMutations,mapState,mapGetters} = Vuex
// 配置仓库对象
let storeCon = {
// 初始化声明属性 项目中公共的属性
state:{
storeMsg:'状态机的msg',
name:'zhangsan',
// stusInfo:[]
},
// 可以获取到state中声明的属性,并且能够进行处理再返回
getters:{
nameUpper(state){
return state.name.toUpperCase()
}
},
// 突变 修改state中的数据仅能在mutations里面进行 payload载荷 参数
mutations:{
changName(state,payload){
console.log('mutations',payload);
state.name = payload
}
},
// 动作 可以异步请求接口
actions:{
getName(context,payload){
console.log('actions',context);
context.commit('changName',payload)
}
}
}
// 状态机 仓库对象
let store = new Vuex.Store(storeCon)
let vm = new Vue({
el:'#app',
data:{
msg:"hello"
},
computed:{
// 辅助函数
// ...Vuex.mapState(['name','storeMsg']),
// ...Vuex.mapGetters(['nameUpper']),
...mapState(['name','storeMsg']),
...mapGetters(['nameUpper']),
},
created(){
console.log('store',this.$store);
console.log('store',this.$store.state);
console.log('getter',this.$store.getters);
console.log(8888,this.changName);
console.log(9999,this.getName);
},
methods:{
// ...Vuex.mapMutations(['changName']),
// ...Vuex.mapActions(['getName']),
...mapMutations(['changName']),
...mapActions(['getName']),
},
// 注册仓库
store:store
})
</script>
</body>
</html>