Vuex
Vuex 是一个专为 Vue.js 开发的状态管理模式。主要是是做数据交互,父子组件传值可以很容易办到,但是兄弟组件间传值(兄弟组件下又有父子组件),页面多并且一层嵌套一层的传值,非常麻烦,这个时候我们就用vuex来维护共有的状态或数据。
vuex一共有五大核心概念
1.state: 用来定义数据的(相当于data),在页面中用获取定义的数据用:
this.$store.state.变量名
- getters:计算属性(相当于vue中的computed),依赖于缓存,只有缓存中的数据发生变化才会重新计算。getters中的方法接收一个state对象作为参数。
如:
state:{
count: 1
},
getters:{
getCount(state) {
return state.count + 1
}
},
在页面中获取用:
this.$store.getters.getCount
<h2>{{this.$store.getters.getCount}}</h2>
- mutations:是修改 state 值的唯一方法,它只能是同步操作
在页面中获取用:
this.$store.commit("方法名")
//可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)
store.commit('increment', 10)
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
-
actions:提交的是 mutations,而不是直接变更状态,它可以包含任意异步操作
-
modules: 模块,Vuex允许将store分割成模块,每个模块都拥有自己的state,getters,mutations,actions,甚至嵌套模块。可以避免变量名相同而导致程序出现问题。
const moduleA = {
state: {},
mutations: {},
actions: {},
getters: {}
}
const moduleB = {
state: {},
mutations: {},
actions: {},
getters: {}
}
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
// 在各自的模块内部使用
state.price // 这种使用方式和单个使用方式一样,直接使用就行
//在组件中使用
store.state.a.price // 先找到模块的名字,再去调用属性
store.state.b.price // 先找到模块的名字,再去调用属性
使用:
安装vuex:
npm install --save vuex
配置vuex
在src文件夹下新增一个store文件夹,里面添加一个index.js文件
然后在main.js中引入store文件下的index.js
// main.js内部对vuex的配置
import store from '@/store/index.js'
new Vue({
el: '#app',
store, // 将store暴露出来
template: '<App></App>',
components: { App }
});
之后我们开始进行store文件下的index.js配置
import Vue from 'vue'; //首先引入vue
import Vuex from 'vuex'; //引入vuex
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// state 类似 data
//这里面写入数据
},
getters:{
// getters 类似 computed
// 在这里面写个方法
},
mutations:{
// mutations 类似methods
// 写方法对数据做出更改(同步操作)
},
actions:{
// actions 类似methods
// 写方法对数据做出更改(异步操作)
}
})
举例:
在store中定义商品的原价,计算折扣价,根据用户输入的数量和商品原价计算出总价
【1】我们约定store中的数据是以下形式
import Vue from 'vue'; //首先引入vue
import Vuex from 'vuex'; //引入vuex
Vue.use(Vuex)
export default new Vuex.Store({
state: {
price: 100, // 原价
total: '', // 总价
},
getters:{
// 折扣价
discount(state, getters) {
return state.price*0.8
}
},
mutations:{
// 计算总价:第一个参数为默认参数state, 后面的参数为页面操作传过来的参数
getTotal(state, n) {
return state.total = state.price * n;
}
},
actions:{
// 这里主要是操作异步操作的,使用起来几乎和mutations方法一模一样
// 除了一个是同步操作,一个是异步操作,一个使用commit调用,一个使用dispatch调用
// 这里就不多介绍了,有兴趣的可以自己去试一试,
// 比如你可以用setTimeout去尝试一下
}
})
【2】在页面中使用store中的数据
```javascript
<template>
<div>
<p>原价:{{price}}</p>
<p>8折:{{discount}}</p>
<p>数量:<input type="text" v-model="quantity"></p>
<p>总价:{{total}}</p>
<button @click="getTotal">计算总价</button>
</div>
</template>
<script>
export default {
data() {
return {
quantity: 0,
}
},
computed: {
price() {
return this.$store.state.price
},
discount() {
return this.$store.getters.discount
},
total() {
return this.$store.state.total
}
},
mounted() {
},
methods: {
getTotal() {
this.$store.commit('getTotal', this.quantity)
}
},
}
</script>
【3】页面效果
再举例应用场景:
比如登录页面,既可以用手机号验证码登录,也可以用手机号密码登录,进行切换的时候想保留输入的手机号码,这个时候我们可以用vuex。
页面刷新数据丢失问题:
vuex存储的数据作为全局的共享数据,是保存在运行内存中的,当页面刷新时,会重新加载vue实例,vuex里的数据会重新初始化,从而导致数据丢失。
怎么解决?
直接在vuex修改数据方法中将数据存储到浏览器缓存中(sessionStorage、localStorage、cookie)
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
orderList: [],
menuList: []
},
mutations: {
orderList(s, d) {
s.orderList= d;
window.localStorage.setItem("list",jsON.stringify(s.orderList))
},
menuList(s, d) {
s.menuList = d;
window.localStorage.setItem("list",jsON.stringify(s.menuList))
},
}
})
在页面加载时再从本地存储中取出并赋给vuex
if (window.localStorage.getItem("list") ) {
this.$store.replaceState(Object.assign({},
this.$store.state,JSON.parse(window.localStorage.getItem("list"))))
}