一、Vuex Store介绍
1、vuex带来的好处:
- 组件之间数据共享
- 组件中数据持久化
- 使用 Vuex 可用使数据流变得清晰、可追踪、可预测
- 使用 Vuex 管理 store 会大大提高项目的稳定性、扩展性
2、Vuex核心:
- state:存储基本数据
- getter:从基本数据(state)派生的数据,相当于state的计算属性
- mutation : store中更改state数据状态的唯一方法(mutations必须是同步函数)
- action: 包含异步操作(请求API方法)、回调函数提交mutaions更改state数据状态,使之可以异步。
- module: 模块化Vuex(将store分割成不同的模块)
二、安装引入
本项目示例通过vue cli4脚手架搭建
1.引入vuex库
npm install vuex --save
2.引入store模块
在main.js引入store模块
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
createApp(App)
.use(store)
.use(router)
.mount("#app");
三、使用操作
1.基本使用
以下是通过对用户信息的用户名进行数据操作为例
(1) store目录下的的index.js
import {createStore} from 'vuex'
export default createStore({
state: {
username:'lss0555'
},
mutations: {
setUserName(state,username){
state.username=username
}
},
getters:{
getUserName(state){
return 'my name is '+state.username
}
},
actions: {
getUserInfo({ state,commit }){
new Promise(resolve => {
setTimeout(() => {
//随机生成一个随机数1-10
var num=Math.floor((Math.random()*10)+1)
//提交修改username属性
commit("setUserName",'lss00'+num);
//返回处理结果
resolve();
}, 1000);
});
}
},
modules: {}
})
(2) 用户组件UserInfo.vue
<template>
<h2>获取用户名方式1:{{username1}}</h2>
<h2>获取用户名方式2:{{username2}}</h2>
<h2>获取用户名方式3:{{username3}}</h2>
<h2>获取用户名方式4:{{$store.state.username}}</h2>
<button @click="updateName">修改用户名方式1</button>
<button @click="setUserName('lss0888')">修改用户名方式2</button>
<button @click="setUserName1('lss0999')">修改用户名方式3</button>
<div/>
<button @click="syncUpdateName">异步获取用户名1</button>
<button @click="getUserInfo">异步获取用户名2</button>
<button @click="syncUpdateName1">异步获取用户名3</button>
</template>
<script>
import {mapState, mapActions, mapMutations} from 'vuex'
export default {
name: "userinfo",
data() {
return {}
},
computed: {
username1() {
return this.$store.state.username
},
...mapState({
username2: state => state.username,
username3(state) {
return state.username;
}
}),
},
methods: {
updateName() {
this.$store.commit('setUserName', 'lss0666')
},
syncUpdateName() {
this.$store.dispatch('getUserInfo')
},
...mapMutations(['setUserName']),
...mapMutations({
setUserName1: "setUserName"
}),
...mapActions(["getUserInfo"]),
...mapActions({
syncUpdateName1: "getUserInfo"
}),
}
}
</script>
<style scoped>
</style>
其中:
(1) 获取state数据的方法
//方式一
this.$store.state.username
...mapState({
//方式二
username2: state => state.username,
//方式三
username3(state) {
return state.username;
}
})
(2)通过getter方法获取对state数据处理后的数据
//index.js
getters:{
getUserName(state){
return 'my name is '+state.username
}
},
//UserInfo.vue
mounted(){
this.username4=this.$store.getters.getUserName
},
(3)通过Mutations修改state数据方法
//方式一
this.$store.commit('setUserName', 'lss0666')
//方式二
...mapMutations(['setUserName']),
//方式三
...mapMutations({
setUserName1: "setUserName"
}),
(4)通过Action异步调用方法
//方式一
this.$store.dispatch('getUserInfo')
//方式二
...mapActions(["getUserInfo"]),
//方式三
...mapActions({
syncUpdateName1: "getUserInfo"
}),
效果图
2.store文件优化
由于在store目录下的index.js里包含着state,actcion,mutations,getters模块,如果你的 store 文件太大,将不利于后期代码的维护,下面则对该文件进行优化,只需将 action、mutation 和 getter 分割到单独的文件在store目录下,在store目录下新建state.js,actions.js,getters.js,mutations.js目录,如下:
(1) state.js
export default {
username:'lss0555'
}
(2) getters.js
export default {
getUserName(state){
return 'my name is '+state.username
}
}
(3) mutations.js
export default {
setUserName(state,username){
state.username=username
}
}
(4)actions.js
export default {
getUserInfo({ state,commit }){
new Promise(resolve => {
setTimeout(() => {
//随机生成一个随机数1-10
var num=Math.floor((Math.random()*10)+1)
//提交修改username属性
commit("setUserName",'lss00'+num);
//返回处理结果
resolve();
}, 1000);
});
}
}
(5)index.js
import {createStore} from 'vuex'
import state from './state.js'
import actions from './actions.js'
import getters from './getters.js'
import mutations from './mutations.js'
export default createStore({
state,
actions,
getters,
mutations,
modules: {}
})
3.store分模块modules化
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。将以上的用户信息模块分为用户模块user以及用户模块1两部分。则目录为以下:
其中,user与user1下面是基本一致代码,user与user1目录下的index.js内容以下:
import state from './state.js'
import actions from './actions.js'
import getters from './getters.js'
import mutations from './mutations.js'
export default {
namespaced:true,
state:state,
actions:actions,
getters:getters,
mutations:mutations
}
其中加入namespaced属性为true,则之后在不同页面中引入getter、actions、mutations时,需要加上所属的模块名。
页面UserInfo.vue如下:
<template>
<h1>用户模块一</h1>
<h2>获取用户名方式1:{{username1}}</h2>
<h2>获取用户名方式2:{{username2}}</h2>
<button @click="updateName">修改用户名方式1</button>
<button @click="setUserName('lss0888')">修改用户名方式2</button>
<div/>
<button @click="syncUpdateName">异步获取用户名1</button>
<button @click="syncUpdateName2">异步获取用户名2</button>
<h1>用户模块二</h1>
<h2>获取用户名方式1:{{username3}}</h2>
<h2>获取用户名方式2:{{username4}}</h2>
<button @click="updateName1">修改用户名方式1</button>
<button @click="setUserName1('lss0777')">修改用户名方式2</button>
<div/>
<button @click="syncUpdateName1">异步获取用户名1</button>
<button @click="syncUpdateName3">异步获取用户名2</button>
</template>
<script>
import {mapState, mapActions, mapMutations} from 'vuex'
export default {
name: "userinfo",
data() {
return {}
},
computed: {
username1() {
return this.$store.state.user.username
},
username3() {
return this.$store.state.user1.username
},
...mapState({
username2: state => state.user.username,
username4: state => state.user1.username,
}),
},
methods: {
//use模块
updateName() {
this.$store.commit('user/setUserName', 'lss0666')
},
syncUpdateName() {
this.$store.dispatch('user/getUserInfo')
},
...mapMutations('user',{
setUserName: "setUserName"
}),
...mapActions('user',{
syncUpdateName2: "getUserInfo"
}),
//user1模块
updateName1() {
this.$store.commit('user1/setUserName', 'lss0333')
},
syncUpdateName1() {
this.$store.dispatch('user1/getUserInfo')
},
...mapMutations('user1',{
setUserName1: "setUserName"
}),
...mapActions('user1',{
syncUpdateName3: "getUserInfo"
}),
}
}
</script>
<style scoped>
</style>
user与user1模块虽然代码一样,但是都是单独的模块,数据互不干扰。
效果图如下: