Vuex是什么?

官网解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

场景:多个页面共享数据时使用Vuex

  • 用户的个人信息管理模块;
  • 从订单结算页,进入选择优惠券的页面,选择优惠券的页面。如何保存选择的优惠券信息?state保存优惠券信息,选择优惠券时, - - - mutations提交,在订单结算页,获取选择的优惠券,并更新订单优惠信息;
  • 购物车模块,每次都调用获取购物车数量的接口,效果是实现了,但是每一次的HTTP请求,都是对浏览器性能消耗。
  • 我的订单模块,订单列表也点击取消订单,然后更新对应的订单列表,这种情况也是用Vuex,state储存一个状态,监听这个状态,变化时更新对应的列表;

Vuex 背后的基本思想,借鉴了 Flux、Redux。与其他模式不同的是,Vuex 是专门为 Vue 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。

vuex使用周期图

在这里插入图片描述

我的store目录

在这里插入图片描述

  • modules是存放不同的模块
  • action-types.js 是为了方便管理,字符串的映射,规范化的管理方式
  • mutation-types.js也是为了方便管理,试想一下,一大堆的功能模块混合在一起,那是多糟糕。
  • index.js

实现一个vuex的示例

让我们创建这几个文件

action-types.js

// 获取用户信息
export const QUERY_USER_INFO = "QUERY_USER_INFO"

mutation-types.js

// 设置用户信息
export const SET_USER_INFO = 'SET_USER_INFO'

在modules下面创建一个base.js文件
base.js

import { QUERY_USER_INFO } from '../action-types'
import { SET_USER_INFO, SET_CUR_MENU_ID } from '../mutation-types'
import api from '@/assets/js/api.js'

// 创建state
const state = {
    // 用户信息
    userInfo: {},
}

// 异步获取数据,commit给mutations,mutations改变state
const actions = {
    /* 获取用户信息 */
    [QUERY_USER_INFO] ({ commit }, params) {
        return api.get({
                url: '/system/getUser',
            }, params.vm).then(data => {
                commit(SET_USER_INFO, data)
                return data
        })

    }

}

const getters = {
    // 当前用户信息
    userInfo: state => state.userInfo
}

// 同步获取
const mutations = {
    [SET_USER_INFO] (state, data) {
        state.userInfo = data
    }
}


export default {
    state,
    actions,
    getters,
    mutations
}

index.js

mport Vue from "vue"
import Vuex from "vuex"
import base from "./modules/base.js"

Vue.use(Vuex);

export default new Vuex.Store({
    modules: {
        base
    }
})

Header.vue

<span>{{$store.getters.userInfo.name}}</span>

main.js

import Vue from 'vue'
import store from './store'
import { QUERY_USER_INFO } from '@/store/action-types.js'

store.dispatch(QUERY_USER_INFO, {}).finally(() => {
    new Vue({
        router: router(store),
        store,
        render: h => h(App)
    }).$mount('#app')
})

Vue组件之间State共享数据Vuex

Vuex
1. 介绍
什么是Vuex:

官网:https://vuex.vuejs.org/zh/

Vuex 是一个专为 Vue.js 应用程序开发的数据状态管理模式。
它采用集中式存储管理应用中所有组件的共享数据,Vuex是组件之间数据共享的一种机制。

2. 为什么要有Vuex
父子组件传值或兄弟组件传值,太麻烦了,不好管理。

vuex提供了一种全新的数据共享管理模式,该模式相比较简单的组件传值更加高端、大气、上档次。

注意:

只有组件间共享的数据,才有必要存储到vuex中,组件自己私有的数据,还是要存储到自己的data中;
在应用的时候要因地制宜,普通组件传值 和 vuex 适合应用在不同场合,要注意区分。

3. 初始化vuex
步骤:

安装vuex
npm i vuex

在这里插入图片描述

main.js做如下设置

import Vue from 'vue'
import App from './App.vue'
// 使用Vuex
// 1. 导入vuex模块
import Vuex from 'vuex'

// 2. Vue对Vuex进行注册
//    之后在组件内部就可以使用vuex的相关成员了
//    Vue.prototype.$store = xxx
Vue.use(Vuex) // 插件应用

// 3. 实例化vuex对象,并做具体配置
//    new Vuex.Store() 是固定用法
//    store:名字暂时是固定的,因为后续对其有使用
const store = new Vuex.Store({
  // state:固定标志,给Vuex配置"共享数据",通过对象成员体现
  state: {
    // 具体数据,数据名称可以自定义,数量不限制
    count: 25,
    count1: 26
    // ……
  }
})

Vue.config.productionTip = false

new Vue({
  // 4. 对vuex进行挂载
  store, // 简易成员赋值,store:store
  render: h => h(App)
}).$mount('#app')

4. 访问vuex共享的数据

4. 访问vuex共享的数据
4.1. state
语法:

this.$store.state.xxx   	// 组件内,xxx:代表共享数据的名称
$store.state.xxx 	        // 模板中,xxx:代表共享数据的名称

应用:

给First.vue设置如下代码:

<template>
    <div id="first">
      <p>我是大哥组件</p>
      <p>count的值为:{{$store.state.count}}</p>
    </div>
</template>

注意:

vuex数据既可以在模板中被访问,语法 $store.state.xxx。
也可以在组件实例内部被访问,语法 this.$store.state.xxx。

4.2. mapState

组件中的Vuex数据如果需要频繁被访问,那么类似这样的代码 this.$store.state.xxx 或 
$store.state.xxx 需要被重复编写,显然,这个代码有点过于复杂,会增加很多工作量,
有没有简便的方式处理呢?

可以使用mapState方式访问state成员

使用步骤:

在应用组件里边按需导入 mapState 辅助函数:

import { mapState } from "vuex";

定义计算属性:

computed: {
	// 通过展开运算符,把state中的数据映射为计算属性
  ...mapState([xx,yy,zz……])
}

// mapState函数本质为如下:
function mapState(arr){
  return {
    arr[0]:function(){
      return this.$store.state.arr[0]
    },
    arr[1]:function(){
      return this.$store.state.arr[1]
    }
    ……
  }
}


然后在组件中就可以像访问data一样访问Vuex成员了。

使用示例:
在Second.vue组件中通过mapState方式设置并访问共享数据:

<template>
    <div id="second">
      <p>我是小弟组件</p>
      <p>count的值为:
        <!--类似访问普通data成员一样,访问vuex数据-->
        {{count}}
        {{count1}}
      </p>
    </div>
</template>

<script>
// 通过mapState对共享数据做简化获取处理
import { mapState } from 'vuex'
export default {
  name: 'second',
  // 计算属性
  computed: {
    // 处理mapState,三个点是做展开运算的,运算结果与后边的内容是一致的
    ...mapState(['count', 'count1'])
    // 通过mapState对下述成员做简化处理
    // ...mapState(['count']) 是做展开操作,获得类似如下的函数
    // count: function () {
    //   return this.$store.state.count
    // },
    // count1: function () {
    //   return this.$store.state.count1
    // }
  }
}
</script>

注意:

如果有多个成员都要经过mapState配置,可以这样...mapState([xx,yy,zz])。
mapState是把state共享数据配置为computed计算属性的成员。

5. 修改(同步)state共享数据

同步修改store中state上的值,需要借助mutations。通过mutations对state共享数据进行修改。

5.1. mutations
语法:

// 在实例化Vuex对象的参数对象中,定义mutations成员(与state平级)对象
mutations:{
  // 参数state是固定的,代表vuex本身的state(名称可以自定义,为了可读性就用state即可),
  // 可以用以获取其中的共享数据
  // 第二个参数可以接收应用层参数信息
	方法名称: function(state,形参){
	    // 通过state修改内部的数据
        state.xx = 形参
	}
}

调用 mutations:

// 组件实例调用
this.$store.commit('mutations方法名')
this.$store.commit('mutations方法名',实参)
// 模板中调用
$store.commit('mutations方法名')  
$store.commit('mutations方法名',实参)

使用示例:
1、给vuex声明 mutations 和相关成员

// mutations:固定标志,对共享数据做同步修改操作
mutations: {
  // 声明修改数据的各个方法
  // mod是自定义名称
  // 参数state,可以自定义,但是就用state,可读性好,意思固定,就代表内部state对象成员(但是它们不是同一个对象)
  // 参数data,是自定义的,可以接收应用层的数据信息
  mod: function (state, data) {
    // 对共享数据最修改
    state.count += data
  }
}


2、在First.vue中调用 mutations 成员

<template>
  <div id="first">
    <p>我是大哥组件</p>
    <p>count的值为:{{$store.state.count}}</p>
    <p>
      <button @click="$store.commit('mod', 10)">修改count</button>
    </p>
  </div>
</template>

注意:

在组件实例内部可以通过this调用,例如 this.$store.commit('mod',10)。
调用一次或多次都可以。
不要对this.$store.state.xxx 直接修改,容易造成数据混乱,因为许多组件都可以这样干。

**********************************************
5.2. mapMutations
组件中的Vuex数据如果需要频繁被修改,那么类似这样的代码 this.$store.commit(xx,yy) 需要被重复编写,显然,这个代码有点过于复杂,会增加很多工作量,有没有简便的方式处理呢?

可以使用 mapMutations

在应用组件中做mapMutations 的模块化导入操作:

import { mapMutations } from "vuex";

在methods方法中做如下设置:

methods: {
  ...mapMutations([xx,yy,zz……])
}

// mapMutations 函数本质为如下:
function mapMutations(arr){
  return {
    arr[0]:function(arg){
      return this.$store.commit(arg)
    },
    arr[1]:function(arg){
      return this.$store.commit(arg)
    }
    ……
  }
}

注意:

mapState 是在computed中做展开,mapMutations是在methods中做展开。

xx/yy/zz 是mutations成员名称,一个或多个都可以。

现在可以像访问methods方法一样直接访问mutations成员。

**********************************************
应用示例:在Second.vue中做如下配置:
<template>
  <div id="second">
    <p>我是小弟组件</p>
    <p>
      count的值为:
      <!--类似访问普通data成员一样,访问vuex数据-->
      {{count}}
      {{count1}}
    </p>
    <p>
      <!-- 如下代码冗余度很高 -->
      <!-- <button @click="$store.commit('mod', 10)">修改count</button>
      <!-- 用简便方式实现数据修改mapMutations,让mutations方法转变为methods方法-->
      <button @click="mod(10)">修改count</button>
    </p>
  </div>
</template>

<script>
// 通过mapState对共享数据做简化获取处理
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'second',
  // 计算属性
  computed: {
    // 处理mapState,三个点是做展开运算的,运算结果与后边的内容是一致的
    ...mapState(['count', 'count1'])
    // 通过mapState对下述成员做简化处理
    // count: function () {
    //   return this.$store.state.count
    // },
    // count1: function () {
    //   return this.$store.state.count1
    // }
  },
  methods: {
    // 应用mapMutations
    ...mapMutations(['mod'])
    // 最终要通过 mapMutations 获得如下相关的方法
    // ...mapMutations(['mod']) 做展开操作,获得类似如下的函数
    // mod (arg) {
    //  return this.$store.commit('mod', arg)
    // }
  }
}
</script>

6. 修改(异步)state共享数据

mutations 和 actions 两个项目都是对Vuex的共享数据做修改的,它们的区别是:

mutations用在同步数据修改操作上
actions用在异步数据修改操作上
什么地方有异步操作:

1、ajax/axios
2、setTimeout
3、fs.readFile()
4、……

6.1. actions
通过 actions 实现异步方式修改 vuex 的数据信息

声明语法:

// actions:固定标志,对共享数据做异步修改
actions: {
  // 声明修改数据的成员方法,数量不限制
  // 参数context:可以自定义,但是就用context(官方就用之),是一个对象,
  // 具体代表$store(它们不是同一个对象)
  // 参数data:可以自定义名称,用于可以接收应用层的数据信息
  成员名称: function (context, data) {
    // actions规定要通过调用mutations成员修改数据(vuex内部规定的)
    context.commit(mutations成员,实参)
  }
}


调用语法:

1this.$store.dispatch('xx',参数)  // 组件内部,xx:代表actions内部成员名称
2、$store.dispatch('xx',参数)       // 模板,xx:代表actions内部成员名称

使用示例:

在vuex中通过actions声明成员,实现异步修改数据操作

actions: {
    xiu: function (context, data) {
      // 通过setTimeout实现“异步”请求,定时1s后执行
      setTimeout(() => {
        context.commit('mod', data)
      }, 1000)
    }
}
// 请求过来后停顿1秒后再操作,体现异步

First.vue中调用actions方法

<p>
    <button @click="$store.dispatch('xiu',10)">异步修改count</button>
</p>

6.2. mapActions

组件中的Vuex数据需要频繁被修改,那么类似这样的代码 this.$store.dispatch(xxx) 需要被重复编写,显然,这个代码有点过于复杂,会增加很多工作量,有没有简便的方式处理呢?

可以使用mapActions。

使用步骤:

1、在应用组件中做mapActions 的模块化导入操作

import { mapActions } from "vuex";

2、在 methods 方法中做如下设置

methods: {
	...mapActions([xx,yy,zz])
}

// mapActions 函数本质为如下:
function mapActions(arr){
  return {
    arr[0]:function(arg){
      return this.$store.dispatch(arg)
    },
    arr[1]:function(arg){
      return this.$store.dispatch(arg)
    }
    ……
  }
}


注意:

mapActions是在methods中做展开,xx/yy/zz 是actions成员名称,一个或多个都可以。
现在可以像访问methods方法一样访问actions成员了
应用示例:

Second.vue中设置如下代码:


<template>
  <div id="second">
    <p>我是小弟组件</p>
    <p>
      count的值为:
      <!--类似访问普通data成员一样,访问vuex数据-->
      {{count}}
      {{count1}}
    </p>
    <p>
      <!-- 如下代码冗余度很高 -->
      <!-- <button @click="$store.commit('mod', 10)">修改count</button>
	  <!-- 用简便方式实现数据修改mapMutations,让mutations方法转变为methods方法-->
      <button @click="mod(10)">修改count</button>
    </p>
    <p>
      <!-- <button @click="$store.dispatch('xiu',10)">修改(异步)count</button> -->
      <!-- 异步方式修改数据,用简便方式实现,像调用methods方法一样,去调用actions成员 -->
      <button @click="xiu(10)">修改(异步)count</button>
    </p>
  </div>
</template>

<script>
// 通过mapState对共享数据做简化获取处理
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
  name: 'second',
  // 计算属性
  computed: {
    // 处理mapState,三个点是做展开运算的,运算结果与后边的内容是一致的
    ...mapState(['count', 'count1'])
    // 通过mapState对下述成员做简化处理
    // count: function () {
    //   return this.$store.state.count
    // },
    // count1: function () {
    //   return this.$store.state.count1
    // }
  },
  methods: {
    // 应用mapMutations
    ...mapMutations(['mod']),
    // 最终要通过 mapMutations 获得如下相关的方法
    // mod (arg) {
    //   this.$store.commit('mod', arg)
    // }

    // actions成员越多,越能体现mapActions的优势
    ...mapActions(['xiu'])
    // 上述语句会生成下述函数
    // xiu (arg) {
    //   执行动作不需要return
    //   要获得返回值才需要return
    //   this.$store.dispatch('xiu', arg)
    // }
  }
}
</script>

注意:

mutations 也可以实现异步方式操作数据,为什么不这样做呢?

1、devtools调试工具有延迟,造成调试有误差。
2、比较混乱,不成规矩。
3、Vuex倡导者也不推荐这样干。

在这里插入图片描述

上图来自官网,说明的事情有如下:

1、Actions拥有与后端接口直接交互的特权,一般都是异步操作。
2、Actions对mutations进行调用,调用 commit。
3、mutations的操作可以直观反映在devtools调试工具中,方便程序调试。
4、mutations对state进行直接操作。
5、state状态数据可以渲染给组件显示。
6、组件实例通过 dispatch 调用actions。

参考
https://blog.csdn.net/jyn15159/article/details/109030523

vue——store全局存储

业务场景:刷新页面时,首次拉取所有配置,存储到store状态管理用于全局调用

import Vue from 'vue'
import Vuex from 'vuex'
import userInfo from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    userInfo, // 用户信息:读取方式this.$store.state.userInfo.xxxx.xx
  },
  state: { // 初始状态或更新后的状态,读取方式:this.$store.state.businessInfo.id;
    businessInfo: {// 业务信息:省去了一层中间参数
      cname: '',
      ename: '',
      id: ''
    }
  },
  mutations: { // 更新状态内容:this.$store.commit('GET_CREDID_INFO', businessInfo);
    GET_BUSINESS_INFO (state, newInfo) {
      state.businessInfo = newInfo
    }
  },
  actions: { //触发状态更新,当需要更新多个状态的时候使用,如this.$store.dispatch('getBusinessInfo', newInfo);
    getBusinesInfo({ commit, state }, newInfo) {
      // commit('GET_USER_INFO', newInfo.userInfo)
    commit('GET_BUSINESS_INFO',newInfo.businessInfo)
    }
  }
})

为避免状态命名重复,使用modules进行管理:

const state = {// 全局参数的初始状态
  credid: '', // 应用管理:配置、发布的credid
  data: null // 是否返回应用(特征)管理首页
}

const mutations = { // 更新全局状态
  SET_APP_CREDID (state, val) {
    state.credid = val
  },
  SET_APP_MANAGE (state, val) {
    state.data = val
  }
}
const actions = { // 可以不设置触发动作
  setAppManage ({ commit }, val) {
    commit('SET_APP_MANAGE', val)
  }
}

export default {
  state,
  mutations,
  actions
}

解决vue刷新页面以后丢失store的数据问题

刷新页面时vue实例重新加载,store就会被重置,可以把定义刷新前把store存入本地localStorage、
sessionStorage、cookie中,localStorage是永久储存,重新打开页面时会读取上一次打开的页面数据,
sessionStorage是储存到关闭为止,cookie不适合存大量数据。根据我的需求,最合适的是sessionStorage。
beforeunload在页面刷新时触发,可以监听这个方法,让页面在刷新前存store到sessionStorage中。
当然,在页面刷新时还要读取sessionStorage中的数据到store中,读取和储存都写在app.vue

Vue - vuex 中 store 中的数据持久化存储,解决刷新页面时 store 中的存储的数据不丢失

vuex 中的数据持久化存储
一. 无需插件实现
二. 使用 vuex-persist 插件实现
Vuex 的使用:https://blog.csdn.net/Jie_1997/article/details/107228246
Vuex 中 store 保存的数据,当刷新页面时数据会清空,如何解决刷新页面时 store 中存储的数据不丢失?

一. 无需插件实现
1、更改 store.js 文件 state 的定义
state:sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')): {
  userData: {}
},1 

2、在 App.vue 中添加:

mounted() {
  window.addEventListener('unload', this.saveState)
},
methods: {
  saveState() {
    sessionStorage.setItem('state', JSON.stringify(this.$store.state))
  },
},

图1
在这里插入图片描述
图2
在这里插入图片描述

二. 使用 vuex-persist 插件实现

安装 vuex-persist
npm install vuex-persist --save

引入vuex-persist

 import VuexPersist from 'vuex-persist'

创建对象,借助浏览器缓存,存入localStorage

const vuexLocal = new VuexPersist({
    storage: window.localStorage  // 可选存储方式
})

vuex.Store 中引入该插件

plugins: [vuexLocal.plugin]

一个实例:图3

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

// 引入vuex-persist
import VuexPersist from 'vuex-persist';
// 创建对象,借助浏览器缓存,存入localStorage
const vuexLocal = new VuexPersist({
    storage: window.localStorage  // 可选存储方式
})

export default new Vuex.Store({
    state: {
        id: 1
    },
    mutations: {
        editId(state, id) {
            state.id = id
        }
    },
    // 引入 vuex-persist 插件
    plugins: [vuexLocal.plugin]
})

图3
在这里插入图片描述

vuex中store的值的设置和获取

在这里插入图片描述
在handUser.js 中state中说明变量,mutations中对state中的变量进行赋值,如下图所示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

this.$store.commit 使用

在这里插入图片描述

前言
this.$store.commit和this.$store.dispatch 方法的区别总的来说他们
只是存取方式的不同,两个方法都是传值给vuex的mutation改变state
************************************************************
this.$store.commit()
同步操作
this.$store.commit('方法名',)【存储】
this.$store.state.方法名【取值】
************************************************************
this.$store.dispatch()
异步操作
this.$store.dispatch('方法名',)【存储】
this.$store.getters.方法名【取值】
************************************************************
当操作行为中含有异步操作:
比如向后台发送请求获取数据,就需要使用action的dispatch去完成了。
其他使用commit即可。

commit => mutations,用来触发同步操作的方法。
dispatch => actions,用来触发异步操作的方法。
在 store 中注册了 mutation 和 action,
在组件中用dispatch调用action,
在组件中用commit调用mutation。
************************************************************
//在页面中的使用
//src\pages\lifeInsur_mgr\lifeInsur_renewal\renewalRecord.vue
this.$store.commit('doLogout',123)
//this.$store.commit('方法名',值)
************************************************************
//在Vuex中
//src\store\modules\lifeInsur_mgr\lifeInsur_renewal.js
//修改 state 的值
mutations: {
  doLogout(state) {
    console.log('------修改后的state------',state);
    state.login = false //添加 login 属性
    state.num = 564642131 //添加 num 属性
    state.recordData = {} //将 state 中的 recordData 对象置空
  }
},

srore 中写法
在这里插入图片描述

在这里插入图片描述
页面中写法
在这里插入图片描述
store 原来的值与修改后的值log打印
在这里插入图片描述

关于 引入vuex 的 store 中的state值, 必须在计算属性中书写

<script>
// 使用vux的 mapState需要引入
import { mapState } from "vuex";
 
export default {
  // 官方推荐: 给组件起个名字, 便于报错时的提示
  name: "Header",
  // 引入vuex 的 store 中的state值, 必须在计算属性中书写!
  computed: {
    // mapState辅助函数, 可以快速引入store中的值
    // 此处的login代表,  store文件中的 state 中的 login, 登录状态
    ...mapState(["login"])
  },
  methods: {
    logout() {
      this.$store.commit("doLogout");
    }
  }
};
</script>

路由跳转指定页面

// 路由跳转指定页面
this.$router.push({ path: "/" });
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@阿猫阿狗~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值