美文网首页
Vue之Vuex

Vue之Vuex

作者: 刘_小_二 | 来源:发表于2021-07-30 13:32 被阅读0次

1.Vuex安装

【NPM】

npm install vuex --save

【Yarn】

yarn add vuex

【备注】有的时候在构件Vue项目时,Vuex在项目创建时已经同步安装,并创建相应的文件目录结构,无需在单独安装。当前内容前半部分时基于单独安装Vuex说讲述。

【核心概念】

  1. State
  2. Getters
  3. Mutations
  4. Actions
  5. 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'
    }),
    }
}


相关文章

网友评论

      本文标题:Vue之Vuex

      本文链接:https://www.haomeiwen.com/subject/ehaqvltx.html