Vuex 全局状态管理模式
最近跟师父学了Vuex全局状态管理模式,感觉很重要,但是又怕记不住,所以在这里做下笔记,顺便将思路再捋一遍
事例:在一个组件中选中一件商品,使商品的颜色改变,变成不可选状态;删除商品,使商品的颜色变回原来,变成可选状态。使用Vuex全局状态管理模式。
- 首先在在src目录下新建store文件夹
- 在store文件夹中分别新建index.js、state.js、mutations.js和getters.js文件
具体代码:
- main.js中引入store,为了使页面更美观,书写更简洁,我在这里使用了iVew
import Vue from 'vue'
import iView from 'iview'
import store from './store'
Vue.use(iView )
new Vue({
el: '#app',
store
})
- store文件夹中的index.js引入vuex,并分别因引入state.js、mutations.js和getters.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutation from './muntations'
import getter from './getters'
export default new Vuex.Store({
state,
mutation,
getter
})
- 在state.js中存放状态值,这里需要两个状态值,一个是选择商品时将商品编号保存的数组,还有一个是删除商品时的商品编号
export default {
save_prod: [], //保存商品的编号
del_prod_id: '' //删除商品的编号
}
- 在mutations.js中写方法
export default{
saveProd(state,params){ //保存商品编号的方法
state.save_prod.push(params);
},
delProd(state,prams){ //删除商品编号的方法
state.del_prod_id = params;
state.save_prod.forEach((item,index) => {
//判断要删除的商品编号和保存商品编号数组中的商品编号是否相等,如果相等,将该商品从数组中删除
if(item == params){
state.save_prod.splice(index,1);
}
})
},
clearProd(state){ // 离开该组件跳转到其他页面时,其他页面的商品是否选中状态不受影响
state.save_prod: [];
state.del_prod_id: '';
}
}
- getter相当于计算属性,删除商品时监听商品编号的变化
export default{
getDelProdId(state){
return state.del_prod_id; //返回删除的商品编号
}
}
- prod_table.vue
<template>
<Table border stripe page-size="total" :columns="columns" :data="List"></Table>
</template>
<script>
import { mapGetters } from 'vuex' //引用辅助函数
export default{
data(){
return{
props: {
selectProd: { //接收父组件(select_prod)中的方法
type: Function,
default: null
},
prodDetailId: { //接收父组件(select_prod_detail)中的值,是个数组
type: Arrary,
default: function(){
return []
}
}
},
List: {},
columns: [
{
title: '商品名称',
key: '商品名称',
align: 'center'
},
{
title: '操作',
key: '操作',
align: 'center',
render: (h,params) => {
return h('Button', {
props: {
type: 'primary'
},
style: {
width: '80px',
fontSize: '18px',
padding: '1px 7px 2px',
borderRadius: '3px',
color: '#fff',
backgroundColor: params.row.选中状态 ? '#c5c8ce' : '',
borderColor: params.row.选中状态 ? '#c5c8ce' : ''
},
on: {
'click' : () => {
var _that = this;
if(!params.row.选中状态){ //判断它是否有选中状态
params.row.选中状态 = true; //如果没有选中状态,手动添加选中状态
_that.$store.commit('save_prod',params.row.编号);//使用this.$store.commit()是将商品编号传入全局状态值中,进行保存
_that.$set(_that.List,params.index,params.row); //this.$set将两个数组中的元素进行合并,没有的添加,这里是为了在List数组中添加选中状态字段
_that.selectProd(params.row); //调用父组件中选择商品的方法
}
}
}
}, '选择')
}
}
]
}
},
computed: {
...mapGetter([ //采用辅助函数,为组件创建计算属性以返回getter的返回值
'getDelProdId'
]);
}
watch: { //采用属性监听,监听getter的返回值的变化
getDelProdId(val){
var _that = this;
_that.List.forEach(item => {
if(item.编号 === val){ //判断商品列表中的商品编号与删除选中商品列表中的商品编号是否相同
item.选中状态 = false; //如果相同将商品列表中的商品变为可选状态
_that.$set(_that.List,index,item);
}
})
}
}
}
//在查询商品列表添加一个判断,如果商品为选中状态,那么在查询的时候将该商品变为不可选状态
var selectProd = _that.$store.state.save_prod; //获取全局状态中的状态值
var value = res.data.rows; //获取后台商品信息
selectProd.forEach(id => { //遍历全局状态中的保存商品编号的状态值
value.forEach(item => { //遍历商品列表
if(id == item.编号){ //判断全局状态中的保存商品编号与商品列表的商品编号是否相同
item.选中状态 = true; //如果相同,商品的选中状态变为不可选状态
}
});
});
//同样在查询中再添加一个判断,如果商品列表中的商品编号与父组件中传入的商品编号进行比较,如果相同,则该商品为不可选状态
_that.prodDetailId.forEach(id => {
res.data.rows.forEach((item,index) => {
_that.$set(res.data.rows,index,item);
if(id == item.编号){
item.选中状态 = true;
}
});
});
</script>
- select_prod.vue
<template>
<--!点击按钮选择商品-->
<Button class="bottom-title-right" @click="modal_prod= true">选择商品</Button>
<--!商品弹出框-->
<Modal v-model="modal_prod" :title="选择商品" width="100%" :closable="false">
<--!引用子组件所有商品列表-->
<ProdTable :selectPord="selectProd"></ProdTable>
</Modal>
<--!选中商品列表-->
<Table border stripe :columns="columns" :data="detail"></Table>
</template>
<script>
import ProdTable from './prod_table',
export default{
components: {
ProdTable
},
data(){
return {
modal_prod: false,
detail: {},
prodDetailId: [],
columns: [
{
title: '商品名称',
key: '商品名称',
align: 'center'
},
{
title: '操作',
key: '操作',
align: 'center',
render: (h,params) => {
return h('Button', {
props: {
type: 'error'
},
style: {
width: '80px',
fontSize: '18px'
},
on: {
click: () => {
var _that = this;
_that.detail.splice(params.index,1);
_that.$store.commit('delProd',params.row.商品编号); //将删除的商品编号传入全局状态之中
}
}
},'删除');
}
}
]
}
},
methods: {
selectPord(val){
var _that = this;
var prod = JSON.stringify(_that.detailInfo); //_that.detailInfo是从后台获取的商品信息的字段
var arry = JSON.parse(prod);
arry.商品编号 = val.编号;
arry.商品名称 = val.商品名称
_that.detail.push(arry); //将选中的商品添加到商品列表中
}
},
beforeRouteLeave(to,from,next){ //在离开组件之前,调用mutations中的方法,将保存在全局状态管理中的状态值清空,然后进入下一页面
this.$store.commit('clearProd');
next();
}
}
</script>
- select_prod_detail.vue (选中商品保存后的商品详情页)
<template>
<--!点击按钮选择商品-->
<Button class="bottom-title-right" @click="modal_prod= true">选择商品</Button>
<--!商品弹出框-->
<Modal v-model="modal_prod" :title="选择商品" width="100%" :closable="false">
<--!引用子组件所有商品列表-->
<ProdTable :selectPord="selectProd" :prodDetailId="prodDetailId"></ProdTable>
</Modal>
<--!选中商品列表-->
<Table border stripe :columns="columns" :data="detail"></Table>
</template>
<script>
import ProdTable from './prod_table',
export default{
components: {
ProdTable
},
data(){
return {
modal_prod: false,
detail: {},
prodDetailId: [], //向子组件传值
columns: [
{
title: '商品名称',
key: '商品名称',
align: 'center'
},
{
title: '操作',
key: '操作',
align: 'center',
render: (h,params) => {
return h('Button', {
props: {
type: 'error'
},
style: {
width: '80px',
fontSize: '18px'
},
on: {
click: () => {
var _that = this;
_that.detail.splice(params.index,1);
_that.$store.commit('delProd',params.row.商品编号); //将删除的商品编号传入全局状态之中
}
}
},'删除');
}
}
]
}
},
methods: {
//通过后台获取选中商品后的商品详情列表,将后台返回的选中商品的商品编号传入子组件prod_table.vue中,与子组件中的商品编号比较,如果相同,子组件中的商品为不可选状态
var _that = this;
res.data.detail.forEach(item => {
_that.prodDetailId.push(item.商品编号);
})
},
beforeRouteLeave(to,from,next){ //在离开组件之前,调用mutations中的方法,将保存在全局状态管理中的状态值清空,然后进入下一页面
this.$store.commit('clearProd');
next();
}
}
</script>