安装vuex:
npm install vuex -S
vuex中一共有五个状态:state,getter,mutation,action,module
在src新建 store 文件夹,并且新建 index.js
在 mian.js 全局挂载 vuex:
import { createApp } from 'vue'
import vuex from './store'
import App from './App.vue'
createApp(App).use(vuex).mount('#app')
如何使用?在store/index.js里:
import { createStore } from 'vuex'
const store = createStore({
state:{
name:"小明"
}
})
export default store
1.State:
提供唯一的公共数据源,所有共享的数据统一放在store的state进行存储,类似于vue的data / return
<template>
<div>
<!-- 在标签中直接使用 -->
<p>{{ $store.state.name }} - {{ $store.state.age }} - {{ $store.state.age ? '男' : '女' }}</p>
<p>{{ getName }}</p>
<!-- 通过mapState获取,在页面中直接使用,辅助函数 -->
<p>{{ name + age + sex }}</p>
</div>
</template>
<script>
// 使用 mapState 导出
import { mapState } from 'vuex'
export default {
data() {
return {}
},
mounted() {
// 全局使用
console.log(this.$store.state.name)
},
computed: {
// 通过mapState函数导出变量并获取值
...mapState(["name", "age", "sex"]),
getName() {
return "myName is : " + this.name
}
}
}
</script>
2.Mutation:
同步操作触发方法:
第一种方法是this.$store.commit("mutation声明的方法")
第二种方法是通过mapMutations抛出,直接在methods里通过声明的方法触发mutations声明的方法
案例1:使用commit触发Mutation操作:
store/index.js:
import { createStore } from "vuex";
const store = createStore({
state: {
index: 1,
},
mutations: {
getInfo1(state, params) {
if(state.index < 99){
state.index = +state.index + params;
}
},
getInfo2(state) {
if(state.index > 1){
state.index--;
}
},
},
});
export default store;
index:
<template>
<div>
<button @click="handleChange2">-</button>
<input type="text" v-model="$store.state.index" />
<button @click="handleChange1">+</button>
</div>
</template>
<script>
export default {
data() {
return {}
},
mounted() { },
methods: {
handleChange1() {
this.$store.commit("getInfo1", 1)
},
handleChange2() {
this.$store.commit("getInfo2")
}
}
}
</script>
案例2:使用辅助函数进行操作,具体方法同上:
store/index.js:
import { createStore } from "vuex";
const store = createStore({
state: {
index: 1,
},
mutations: {
getInfo1(state, params) {
if(state.index < 99){
state.index = +state.index + params;
}
},
getInfo2(state) {
if(state.index > 1){
state.index--;
}
},
},
});
export default store;
index:
<template>
<div>
<button @click="handleChange2">-</button>
<input type="text" v-model="$store.state.index" />
<button @click="handleChange1">+</button>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
data() {
return {}
},
mounted() { },
methods: {
...mapMutations(["getInfo1","getInfo2"]),
handleChange1() {
this.getInfo1(1)
},
handleChange2() {
this.getInfo2()
}
}
}
</script>
3.Action:异步操作
异步操作触发方法:
第一种方法是this.$store.dispatch("mutation声明的方法")
第二种方法是通过mapActions抛出,直接在methods里通过声明的方法触发
store/index.js:
import { createStore } from "vuex";
const store = createStore({
state: {},
mutations: {
handleFn() {
alert(123);
},
},
actions: {
getInfo3(content) {
setTimeout(() => {
content.commit("handleFn");
}, 1000);
},
},
});
export default store;
index.js
<template>
<div>
<button @click="handleChange3">aaa</button>
</div>
</template>
<script>
import { mapActions, mapMutations } from 'vuex';
export default {
data() {
return {}
},
mounted() { },
methods: {
...mapActions(["getInfo3"]),
handleChange3(){
this.getInfo3()
}
}
}
</script>
4.Getters:
Getters类似于vue中的computed,进行缓存,对store中的数据进行加工
mapGetters语法:
import { mapGetters } from 'vuex
export default {
computed: {
...mapGetters(['计算属性名'])
...mapGetters('模块名',['计算属性名'])
...mapGetters('模块名',['新计算属性名','新计算属性名'])
}
}
案例1:
store/index.js:
import { createStore } from "vuex";
const store = createStore({
state: {
name: "aabbcc",
},
getters: {
getInfo4(state) {
return state.name + "zzz";
},
},
});
export default store;
index:
<template>
<div>
{{searchMsg}}
</div>
</template>
<script>
export default {
data() {
return {}
},
mounted() { },
computed:{
searchMsg(){
return this.$store.getters.getInfo4
}
}
}
</script>
案例2:
store/index.js:
import { createStore } from "vuex";
const store = createStore({
state: {
nameObj: {
aaa:"xxx",
bbb:"yyy",
ccc:"zzz"
},
},
getters: {
nameObj: state => state.nameObj || {}
},
});
export default store;
index.js:
<template>
<div>
{{searchMsg}}
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data() {
return {}
},
mounted() { },
computed:{
...mapGetters(["nameObj"]),
searchMsg(){
return this.nameObj
}
}
}
</script>
案例3:购物车案例
store/index.js:
import { createStore } from "vuex";
const store = createStore({
state: {
shopList: [
{
shopName: "精品男装运动裤",
shopNum: 1,
shopPrice: 599,
},
{
shopName: "kappa男装外套",
shopNum: 1,
shopPrice: 399,
},
{
shopName: "精品男装运动鞋",
shopNum: 1,
shopPrice: 299,
},
],
},
mutations: {
add(state, params) {
const index = params.index;
const num = state.shopList[index].shopNum;
if (num < 99) {
state.shopList[index].shopNum = +num + params.num;
}
},
reduce(state, params) {
const index = params.index;
const num = state.shopList[index].shopNum;
if (num > 1) {
state.shopList[index].shopNum--;
}
},
},
getters: {
shopData(state) {
return state.shopList;
},
shopPrice(state) {
return state.shopList.reduce((a, b) => {
return a + b.shopPrice * b.shopNum;
}, 0);
},
},
});
export default store;
index:
<template>
<div>
<table border="1" width="400" cellpadding="5">
<tr>
<th>商品名称</th>
<th>商品个数</th>
<th>商品价格</th>
</tr>
<tr v-for="(item,index) in shopList" :key="index">
<td align="center">{{item.shopName}}</td>
<td align="center">
<button @click="handleReduce({num:1,index:index})">-</button>
<input
type="text"
v-model="item.shopNum"
style="width:30px;text-align: center;margin:0 5px;"
/>
<button @click="handleAdd({num:1,index:index})">+</button>
</td>
<td align="center">{{item.shopPrice * item.shopNum}}</td>
</tr>
<tr>
<td colspan="3" align="right">商品总价 : {{shopTotal}}</td>
</tr>
</table>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
data() {
return {}
},
mounted() { },
computed:{
...mapGetters(["shopData","shopPrice"]),
shopList(){
return this.shopData
},
shopTotal(){
return this.shopPrice
}
},
methods:{
...mapMutations(['add','reduce']),
handleReduce(params){
this.reduce(params)
},
handleAdd(params){
this.add(params)
}
}
}
</script>
5.Modules:
Vuex 允许我们将 store 分割成模块(module) 每个模块拥有自己的 state mutation action getter 甚至是嵌套子模块——从上至下进行同样方式的分割:
store/index.js:
import { createStore } from "vuex";
const modulesA = ({
state: {
name:"aaa"
}
});
const store2 = createStore({
state:{},
mutations:{},
getters:{},
actions:{},
modules:{
namespaced:true,
A:modulesA
}
})
export default store2;
index.js
<template>
<div>
{{$store.state.A.name}} // aaa
</div>
</template>
6.vue存储数据 / 获取数据
store/index.js:
import { createStore } from "vuex";
const store2 = createStore({
state:{
formData:{
userName:"",
passWord:""
}
},
mutations:{
toLogin(state,params){
state.formData = params
}
},
getters:{},
actions:{},
modules:{}
})
export default store2
index.vue:
<template>
<div>
<div>
username:<input type="text" v-model="formData.userName" />
</div>
<div>
password:<input type="password" v-model="formData.passWord" />
</div>
<div>
<button @click="handleLogin">Login</button>
</div>
{{$store.state.formData}}
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
data(){
return {
formData:{
userName:"",
passWord:""
}
}
},
methods:{
...mapMutations(['toLogin']),
handleLogin(){
// 第一种写法
this.toLogin(this.formData)
// 第二种写法
this.$store.commit("toLogin",this.formData)
}
}
}
</script>
7.持久化存储
vuex或者pinia都会出现当刷新浏览器的时候,数据会被清空
1) 自己实现一个持久化本地存储
新建一个 SesstionUtils.js
export class SesstionUtils {
static get(key) {
return JSON.parse(window.sessionStorage.getItem(key));
}
static set(key, value) {
window.sessionStorage.setItem(key, JSON.stringify(value));
}
static remove(key) {
window.sessionStorage.removeItem(key);
}
}
index.vue
import { createStore } from "vuex";
import { SesstionUtils } from "./SessionUtils";
const store2 = createStore({
state: {
formData: SesstionUtils.get("loginInfo") || {},
},
mutations: {
toLogin(state, params) {
state.formData = params;
SesstionUtils.set("loginInfo", state.formData);
},
},
getters: {},
actions: {},
modules: {},
});
export default store2;
此时刷新浏览器,发现数据还在,并且在控制台的存储,可以看到通过本地存储的vuex数据
2) 通过 vuex-persistedstate 第三方插件实现:
npm install vuex-persistedstate --save-dev
如何使用:
store/index.js
import { createStore } from "vuex";
// 引用插件
import createPersistedState from 'vuex-persistedstate'
const store2 = createStore({
state:{
formData:{
userName:"",
passWord:""
}
},
mutations:{
toLogin(state,params){
state.formData = params
}
},
getters:{},
actions:{},
modules:{},
// 使用 数据持久化
plugins: [
createPersistedState({
// 存储方式:localStorage、sessionStorage、cookies
storage:window.sessionStorage,
// 存储的 key 的key值
key:"userInfo2",
render(state){
// 要存储的数据:本项目采用es6扩展运算符的方式存储了state中所有的数据
return {...state}
}
})
]
})
export default store2;