官网解释: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'
const state = {
userInfo: {},
}
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'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 25,
count1: 26
}
})
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App)
}).$mount('#app')
4. 访问vuex共享的数据
4. 访问vuex共享的数据
4.1. state
语法:
this.$store.state.xxx
$store.state.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: {
...mapState([xx,yy,zz……])
}
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>
import { mapState } from 'vuex'
export default {
name: 'second',
computed: {
...mapState(['count', 'count1'])
}
}
</script>
注意:
如果有多个成员都要经过mapState配置,可以这样...mapState([xx,yy,zz])。
mapState是把state共享数据配置为computed计算属性的成员。
5. 修改(同步)state共享数据
同步修改store中state上的值,需要借助mutations。通过mutations对state共享数据进行修改。
5.1. mutations
语法:
mutations:{
方法名称: function(state,形参){
state.xx = 形参
}
}
调用 mutations:
this.$store.commit('mutations方法名')
this.$store.commit('mutations方法名',实参)
$store.commit('mutations方法名')
$store.commit('mutations方法名',实参)
使用示例:
1、给vuex声明 mutations 和相关成员
mutations: {
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……])
}
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>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'second',
computed: {
...mapState(['count', 'count1'])
},
methods: {
...mapMutations(['mod'])
}
}
</script>
6. 修改(异步)state共享数据
mutations 和 actions 两个项目都是对Vuex的共享数据做修改的,它们的区别是:
mutations用在同步数据修改操作上
actions用在异步数据修改操作上
什么地方有异步操作:
1、ajax/axios
2、setTimeout
3、fs.readFile()
4、……
6.1. actions
通过 actions 实现异步方式修改 vuex 的数据信息
声明语法:
actions: {
成员名称: function (context, data) {
context.commit(mutations成员,实参)
}
}
调用语法:
1、this.$store.dispatch('xx',参数)
2、$store.dispatch('xx',参数)
使用示例:
在vuex中通过actions声明成员,实现异步修改数据操作
actions: {
xiu: function (context, data) {
setTimeout(() => {
context.commit('mod', data)
}, 1000)
}
}
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])
}
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>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name: 'second',
computed: {
...mapState(['count', 'count1'])
},
methods: {
...mapMutations(['mod']),
...mapActions(['xiu'])
}
}
</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,
},
state: {
businessInfo: {
cname: '',
ename: '',
id: ''
}
},
mutations: {
GET_BUSINESS_INFO (state, newInfo) {
state.businessInfo = newInfo
}
},
actions: {
getBusinesInfo({ commit, state }, newInfo) {
commit('GET_BUSINESS_INFO',newInfo.businessInfo)
}
}
})
为避免状态命名重复,使用modules进行管理:
const state = {
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)
import VuexPersist from 'vuex-persist';
const vuexLocal = new VuexPersist({
storage: window.localStorage
})
export default new Vuex.Store({
state: {
id: 1
},
mutations: {
editId(state, id) {
state.id = id
}
},
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。
************************************************************
this.$store.commit('doLogout',123)
************************************************************
mutations: {
doLogout(state) {
console.log('------修改后的state------',state);
state.login = false
state.num = 564642131
state.recordData = {}
}
},
srore 中写法
页面中写法 store 原来的值与修改后的值log打印
关于 引入vuex 的 store 中的state值, 必须在计算属性中书写
<script>
import { mapState } from "vuex";
export default {
name: "Header",
computed: {
...mapState(["login"])
},
methods: {
logout() {
this.$store.commit("doLogout");
}
}
};
</script>
路由跳转指定页面
this.$router.push({ path: "/" });
|