1.Vuex安装
【NPM】
npm install vuex --save
【Yarn】
yarn add vuex
【备注】有的时候在构件Vue项目时,Vuex在项目创建时已经同步安装,并创建相应的文件目录结构,无需在单独安装。当前内容前半部分时基于单独安装Vuex说讲述。
【核心概念】
- State
- Getters
- Mutations
- Actions
- Modules
2.Vuex初始化
【2.0】创建store文件夹,新建index.js文件。(该文件负责引入具体模块内容)
// 文件夹下模块自动化导入
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
export default new Vuex.Store({
modules
});
// 简单易理解
import Vue from 'vue'
import Vuex from 'vuex'
import common from './modules/common'
import user from './modules/user'
import article from './modules/article'
import message from './modules/message'
import wxUserTags from './modules/wxUserTags'
import wxAccount from './modules/wxAccount'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
common,
user,
article,
message,
wxUserTags,
wxAccount
},
mutations: {
},
strict: true
})
【2.1】创建各种模块js文件(如:common、user、article等)
// 举例-1
const state = {
userinfo: '',
token:"",
loginInfo: [],
//要设置的初始属性值
};
//实时监听state值的变化(最新状态)
const getters = {
getuserinfo(state) { //方法名随意,主要是来承载变化的userinfo的值
return state.userinfo
},
gettoken(state){
return state.token
},
getloginInfo(state){
return state.loginInfo.lenth==0 ? state.loginInfo : JSON.parse(localStorage.getItem("loginInfo"))
},
};
//第一参数未默认参数
//同步,执行this.$store.commit('')
const mutations = {
ChangeUserinfo(state, userinfo) { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
state.userinfo=userinfo
},
Changetoken(state, token) {
state.token=token
},
ChangeloginInfo(state, loginInfo) {
state.loginInfo=loginInfo
window.localStorage.setItem("loginInfo", JSON.stringify(state.loginInfo));
},
};
//异步,执行this.$store.dispatch('')
const actions = {
ChangeUserinfo(context,userinfo) { //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
context.commit('ChangeUserinfo',userinfo);
},
Changetoken(context,token) {
context.commit("Changetoken", token)
},
ChangeloginInfo(context,loginInfo) {
context.commit("ChangeloginInfo", loginInfo)
},
};
export default {
//namespaced:true,//用于在全局引用此文件里的方法时标识这一个的文件名
state,
getters,
mutations,
actions
}
// 举例-2
export default {
// 获取属性时是否需要加上模块名
namespaced: true,
//
state: {
id: 0,
name: '张三丰',
nameLsit: [
{
name: '张',
age: 21
},
{
name: '王',
age: 22
},
{
name: '李',
age: 23
},
{
name: '赵',
age: 24
},
]
},
//
getters: {
getName(state) {
return state.name
},
findName: (state) => (name) => {
return state.nameLsit.find(nameLsit => nameLsit.name === name)
},
addUserid(state) {
return state.id + 1
}
},
//
mutations: {
updateId(state, id) {
state.id = id
},
updateName(state, name) {
state.name = name
}
},
//
actions: {}
}
3.state,mapState,...mapState对象展开符详解
【3.1】属性访问
this.$store.state.user.name // user 模块名, name 对应的值
【3.2】计算属性 - 读取状态值
computed: {
name () {
return this.$store.state.user.name
}
},
// 读取
methods: {
changname(){
console.log('-------------');
console.log('-------------' + this.name);
console.log('-------------' + this.$store.state.user.name);
},
}
在进行页面赋值时,Vuex中state类中的值可以直接赋值到data中,如下
data() {
return {
name: this.$store.state.user.name
}
},
(但该值无法动态修改,会值一直不发生变化,故会选用“computed”来进行读取)
[3.3]mapState
辅助函数
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
[3.3] mapState
辅助函数 - 对象展开运算符
// namespaced: false,
...mapState({
nameMap: state => state.name
}),
// 或者
...mapState('user',{
nameMap: 'name'
}),
// namespaced: true,
...mapState('user',{
nameMap: state => state.name
}),
// 或者
...mapState('user',{
nameMap: 'name'
}),
// 使用
console.log('---' + this.nameMap)
4.getters,mapGetters,...mapGetters详解
getters: {
getProductByid: (state) => (id) =>
{
return state.productList.find(item => item.id === id);
}
}
【3.1】属性访问
在使用了namespace的情况下调用:
this.$store.getters['yournamespace/getProductByid'](id);
在未使用namespace的情况下调用:
this.$store.getters.getProductByid(id);
【3.2】 通过方法访问
computed: {
getName_C() {
return this.$store.getters['user/getName'];
},
getName_Changer() {
return function (value) {
return this.$store.getters['user/findName'](value);
}
},
},
methods: {
getName(){
console.log('-----------');
console.log('---' + JSON.stringify(this.$store.getters['user/findName']('李')))
console.log(' ---' + JSON.stringify(this.getName_Changer('张')))
console.log('----' + this.getName_C);
},
}
【3.3】mapGetters
辅助函数
// namespaced: false,
...mapGetters({
userIds: 'addUserid'
})
// namespaced: true,
...mapGetters('user',{
userIds: 'addUserid'
})
// 使用
console.log('---' + this.userIds)
5.Mutation(同步)
通俗的理解mutations,里面装着一些改变数据方法的集合,这是Vuex设计很重要的一点,就是把处理数据逻辑方法全部放在mutations里面,使得数据和视图分离。切记:Vuex中store数据改变的唯一方法就是mutation!
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation. 这是官方文档的原文. 不要通过其他方式去修改store中的状态, 这点非常关键, 那样做会使状态不收我们管控的.
Vuex 中的 mutation 非常类似于vue中的$emit事件,
-
每个 mutation 都有一个字符串的事件类型 (type) ,相当于当前事件的唯一标识,以便于你用commit触发它.
-
每个mutation都有一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数.同时他也支持额外参数的传入,额外参数的术语叫'载荷'.
【举例分析 - 列-1(普通)】
在stroe中定义一个mutation, 作用是将count++.
mutations:{
addCount(state){
state.count++;
}
},
mutation的第一个参数是state, 通过他我们能拿到state中定义的状态.
// 调用
methods:{
addCountInR1(){
this.$store.commit("addCount");
}
}
// namespaced: false,
this.$store.commit('updateName', nameNew);
// namespaced: true,
this.$store.commit('user/updateName', nameNew);
【mapMutations 辅助函数】
// namespaced: false,
...mapMutations([
'updateName',
]),
...mapMutations({
onUpdateName: 'updateName'
}),
// namespaced: true,
...mapMutations('user',[
'updateName',
]),
...mapMutations('user',{
onUpdateName: 'updateName'
}),
【举例分析 - 列-2(参数)】
给mutation传参, 在改变store中的状态时, 可能需要传递进参数. 再定义一个mutation:addCountWithParams, 实现将count的值与传递的参数相加.
mutations:{
addCount(state){
state.count++;
},
addCountWithParams(state, params){
state.count += params;
},
pushDataToArrat(state){
state.array.push({
name:"sunq",
age:100
})
}
},
组件内传递参数调用
methods:{
addCount(){
this.$store.commit("addCountWithParams", Math.ceil(Math.random() * 20));
}
},
传入一个随机的1-20的整数, 与count相加.
官方推荐传递一个对象参数, 实践中也确实这样, 避免了对参数个数的控制, 而且这样更能和mutation的对象方式的提交组合使用, 写法更简洁.
mutations:{
addCount(state){
state.count++;
},
addCountWithParams(state, params){
state.count += params;
},
addCountWithObjParams(state, params){
state.count += params.num;
}
},
在组件中使用对象的方式调用addCountWithObjParams.
methods:{
addCount(){
//普通方式提交
this.$store.commit("addCountWithObjParams", {
num: Math.ceil(Math.random() * 10)
});
//对象方式提交
this.$store.commit({
type: "addCountWithObjParams",
num: Math.ceil(Math.random() * 10)
});
}
},
上面代码提交了两次, 分别使用普通方式提交和对象风格提交addCountWithObjParams.
6. Action(异步)
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
【写法-1】
//异步,执行this.$store.dispatch('')
const actions = {
ChangeUserinfo(context,userinfo) { //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
context.commit('ChangeUserinfo',userinfo);
},
Changetoken(context,token) {
context.commit("Changetoken", token)
},
ChangeloginInfo(context,loginInfo) {
context.commit("ChangeloginInfo", loginInfo)
},
};
【写法-2】
const store = new Vuex.store({
//在这里定义state/mutations/actions等,且均为对象形式
state:{
num:0
},
mutations:{
numPlusVar(state,var){
state.num += var
}
},
actions:{
// 获取异步的数据 第一个参数context表示当前的store的实例 可以通过 context.state 获取状态 也可以通过context.commit 来提交mutations, 也可以 context.diapatch调用其他的action
asyncAddNum(context,var){
setTimeout(function(){
// 一秒钟之后 去修改state中的num,带参
context.commit('numPlusVar', var)
}, 1000)
}
}
})
【6.1】属性访问
// html
<template>
<div>{{ num }}</div>//0
<button @click="asyncChange">用原始dispacth方法异步修改</button>
</template>
// Js
<script>
import { mapState } from "vuex";
export default {
computed: {
...mapState(["num"])
},
methods:{
//方法1
asyncChange(){
// namespaced: false,
//一秒后+10
this.$store.dispatch('asyncAddNum',10)
// namespaced: true,
this.$store.dispatch('模块名/asyncAddNum',10)
}
}
}
【6.2】mapActions 辅助函数
// html
<template>
<div>{{ num }}</div>//0
<button @click="asyncAddNum(100)">用mapActions方法异步修改</button>//一秒后+100
</template>
// Js
<script>
import { mapState, mapActions } from "vuex";
export default {
computed: {
...mapState(["num"])
},
methods:{
//方法2
// namespaced: false,
...mapActions(['asyncAddNum']),
// namespaced: true,
...mapActions('模块名',['asyncAddNum']),
// 或
...mapActions('模块名',{
别名 : 'asyncAddNum'
}),
}
}
网友评论