首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >在 vue-4.5 中学习 vuex/超详细教程

在 vue-4.5 中学习 vuex/超详细教程

作者头像
玖柒的小窝
修改2021-10-09 14:18:37
修改2021-10-09 14:18:37
9630
举报
文章被收录于专栏:各类技术文章~各类技术文章~

Vue 脚手架中使用 Vuex

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

在脚手架里进行Vuex开发:

Vuex中文文档:vuex.vuejs.org/zh/guide/

一、 使用Vuex实现跨组件修改数据

1.1 效果页面预览

home页面:负责增加数据

about页面:负责减少数据


1.2 Vuex的五个核心概念详解

基础目录结构:默认Vuex代码写在index中,modules模块化代码则放在Addition.js与Subition.js中;state、mutations、actions、getters均有两种调用方式

注:两种调用方式分别使用在 Addition.vue 与 Subition.vue 中

1.2.1 state
代码语言:javascript
复制
export default createStore({
// State提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行存储
  state: {
    // 组件里第一种访问State数据的方式:
    // this.$store.state.全局数据名称;
    count: 0 // this.$store.state.count;简写:$store.state.count
    // 第二种访问State数据的方式:
    // 在需要用到state数据的页面引入:import { mapState } from 'vuex'
    // 将当前组件需要的全局数据,映射为当前组件的computed计算属性
    // ...表示展开运算符,把当前全局数据映射为计算属性
    // ...mapState(['count','更多数据']) ;指定需要引入这个页面的state数据
  },
})
复制代码

第一种方式在Addition页面使用

第二种方式在Subition页面使用

引入mapState

在computed里展开映射为计算属性

在页面中使用

1.2.2 mutations
代码语言:javascript
复制
export default createStore({
	//Mutation用于变更Store中的数据,且只有mutation能够修改state数据
  //Vuex的数据只能通过mutation变更,不可以直接操作Store中的数据
  //用这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
  //但是mutation不能异步操作
  mutations: {
    //mutation里的函数第一个参数默认都是state,这个state表示当前的数据
    countAdd(state){
      state.count++;
    },
    //使用参数进行相加
    countAdds(state,step){
      state.count+=step;
    },
    //第二种使用mutationd的方式;使用mapMutations导入使用mutations方法
    countSub(state){
      state.count--;
    },
    //使用参数进行相加
    countSubs(state,step){
      state.count -= step;
    }
  },
})
复制代码

第一种调用方式

第二种

引入mapMutations

映射进methods

调用

1.2.3 actions
代码语言:javascript
复制
export default createStore({
	//ACtions提供异步操作
  //如果要使用异步操作,就得在actions里进行,
  //但是action还是得通过,触发mutation的方法简介变更数据
  actions: {
    //在actions中不能修改state的数据
    countAddActions(context){ // context为默认参数
      setTimeout( () => {
        context.commit('countAdd') //调用mutations方法
      },1000)
    },
    countAddsActions(context,step){
      setTimeout( () => {
        context.commit('countAdds',step)
      },1000)
    },
    //第二种使用actions方法;使用mapActions导入使用actions方法
    countSubActions(context){
      setTimeout( () => {
        context.commit('countSub')
      },1000)
    },
    countSubsActions(context,step){
      setTimeout( () => {
        context.commit('countSubs',step)
      },1000)
    },
  },
})
复制代码

第一种方法

第二种方法

引入

映射

使用

注:除了mutations使用mapMutations映射进methods调用mutations方法除外的其他调用方法名都可设置为一样的。

1.2.4 getters
代码语言:javascript
复制
export default createStore({
	//Getter用于对Store中的数据进行加工处理,形成新的数据;类似vue的计算属性
  //store中数据发生变化,getter的数据也会发生变化 
  getters: {
    // 调用方法;this.$store.getters.方法名称;this.$store.getters.showCount
    showCount(state){
      return '当前最新的数据是【' + state.count + '】'
    }
  },
})
复制代码

第一种方法

第二种

引入

映射

使用

1.2.5 modules
代码语言:javascript
复制
//由于Vuex使用单—状态树,应用的所有状态会集中到一个比较大的对象。
//Vuex允许将store分割成模块(module)。
//每个模块拥有自己的state、mutation、action、getter、module,
//甚至是嵌套子模块----从上至下进行同样方式的分割。
// 引入模块js
import Addition from './Addition.js'
import Subition from './Subition.js'

export default createStore({
  //使用这两个模块
  modules: {
    Addition,
    Subition
  }
)}
复制代码

使用modules调用vuex与不使用时的区别:

state

代码语言:javascript
复制
// 模块内调用
state.属性名
// 跨模块调用
rootState.模块名.属性名
复制代码

getters

代码语言:javascript
复制
// 模块内调用
getters.属性名
// 跨模块调用
rootGetters.模块名.属性名
复制代码

mutation

代码语言:javascript
复制
// 模块内调用
commit('模块内方法名')
// 跨模块调用
commit('模块名/方法名')
复制代码

action

代码语言:javascript
复制
// 模块内调用
dispatch('模块内方法名')
// 跨模块调用
dispatch('模块名/方法名')
复制代码

示例:新建以下两个文件;并将原本index.js页面的内容分别移入Addition.js与Subition.js文件内

Addition.js页面;namespaced: true;设置命名空间,使其他页面可引入使用这个模块

Subition.js页面

Addition.vue;使用模块方法与数据都需要指定

Subition.vue;相应的map也得指定模块

映射方法后;正常调用

添加数据效果:因为使用的是各自页面的数据,所以展示数据相反

减少数据效果

1.2.6 如果想要修改index.js的数据,达到之前两个页面修改同一个数据的效果:

就得使用跨模块调用:

  • 跨模块使用 state 和 getters 语法:{ rootState,rootGetters }
  • 跨模块调用 mutations 与 actions:{ root:true }

注:先好好理解并消化上面的五种核心;之后的内容因为使用了跨模块调用,稍微有点复杂,所以将代码重新写了一遍。

修改后的 index.js 页面内容

代码语言:javascript
复制
import { createStore } from 'vuex'
import Addition from './Addition.js'
import Subition from './Subition.js'

//这里以counts与msg做例子;其中counts使用rootState进行修改
//msg以设置{root:true}属性来调用mutations修改

export default createStore({
  state: {
    // counts 使用跨模块使用 state
    counts: 0,
    // 跨模块调用 mutations
    msg: 0
  },
  mutations: {
    // 正常调用,使用传多参数的形式进行判断是相加还是相减以及增加或减少多少
    // payload.status: 判断相加还是相减
    // payload.num: 相加减的值
    increment(state, payload) {
      // 判断是否相加
      if (payload.status == 'add') {
        // 进行相加
        state.counts = state.counts += payload.num
        // 判断是否相减
      } else if (payload.status == 'sub') {
        // 相减
        state.counts = state.counts -= payload.num
      } else {
        // 参数传错时
        alert('想啥呢?参数只能是 add 或 sub ' + payload.num + payload.status)
      }
    }
  },
  actions: {
    // 异步调用
    incrementActions(context, num, status) {
      setTimeout(() => {
        context.commit('increment', num, status)
      }, 1000)
    }
  },
  //导入模块
  modules: {
    Addition,
    Subition
  }
})
复制代码

Addition.vue页面:

template组件内容

不异步调用

异步调用

Addition.js页面

AdditionCount 的修改

跨模块修改 counts 与 msg

注:跨模块调用只能用作在 actions 里,不能在mutations里使用(网上搜了一堆教程没有一个指明,害我调了几天的bug)

Subition.vue(省略,可下载源码查看)

一模一样的代码,只是调用方式改变了而已

1.2.7 mutation命名常量化

Vuex官网建议我们给mutations的方法命名为常量:

新建个mutations-type文件将使用的方法在这里声明const:

将所有Vuex页面的mutations都命名到这

代码语言:javascript
复制
//命名并导出
export const 常量名 = 方法名

//在需要使用的页面引入:
import {常量名} from './mutations-type'

// index.js使用方法:
[常量名] (state,payload) {
  state.count += payload
}

// index.vue使用:
方法名(){
  this$store.commit('模块名/' + 常量名, 参数)
}

//map方式引入:
...mapMutations('模块名',[常量名])
//map引入后调用:
方法名() {
  this[常量名](参数)
}
复制代码

index.js:

Addition.js:

Addition.vue:

Subition.vue:

代码过于复杂只看图示可能看不明白(ps:我自己也看不明白)

建议直接下载源代码查看

总结

在 Vuex中说白了,任何的操作都是围绕state来进行的, Vuex是状态管理器,作用就是管理state 中的状态,其他提供的所有功能Getter、Mutation、Action、Modules都是为了能够更好的管理state,而之所以设计成期望通过Mutation改变状态,是因为我们期望所有状态的变化都是有迹可循的!

运作图

1.3 未使用模块化的详细代码

1.3.1 store文件夹下的index.js文件
代码语言:javascript
复制
import { createStore } from "vuex";

export default createStore({
  //State提供唯一的公共数据源,所有共享的数据都要统一放到
  //Store的State中进行存储
  state: {
    //组件里第一种访问State数据的方式:
    // this.$store.state.全局数据名称;this.$store.state.count
    count: 0
    //第二种访问State数据的方式:
    // import { mapState } from 'vuex';通过导入mapState函数
    // 将当前组件需要的全局数据,映射为当前组件的computed计算属性
  },
  //Mutation用于变更Store中的数据,且只有mutation能够修改state数据
  //Vuex的数据只能通过mutation变更,不可以直接操作Store中的数据
  //用这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
  //mutation不能异步操作
  mutations: {
    //mutation里的函数第一个参数都默认是state,这个state表示当前的数据
    countAdd(state){
      state.count++;
    },
    //使用参数进行相加
    countAdds(state,step){
      state.count+=step;
    },
    //第二种使用mutationd的方式;使用mapMutations导入使用mutations方法
    countSub(state){
      state.count--;
    },
    //使用参数进行相加
    countSubs(state,step){
      state.count -= step;
    }
  },
  //ACtions提供异步操作
  //如果要使用异步操作,就得在actions里进行,但是action还是得通过
  //触发mutation的方法简介变更数据
  actions: {
    //在actions中不能修改state的数据
    countAddActions(context){
      setTimeout( () => {
        context.commit('countAdd')
      },1000)
    },
    countAddsActions(context,step){
      setTimeout( () => {
        context.commit('countAdds',step)
      },1000)
    },
    //第二种使用actions方法;使用mapActions导入使用actions方法
    countSubActions(context){
      setTimeout( () => {
        context.commit('countSub')
      },1000)
    },
    countSubsActions(context,step){
      setTimeout( () => {
        context.commit('countSubs',step)
      },1000)
    },
  },
  //Getter用于对Store中的数据进行加工处理,形成新的数据;类似vue的计算属性
  //store中数据发生变化,getter的数据也会发生变化 
  getters: {
    // 调用方法;this.$store.getters.方法名称;this.$store.getters.showCount
    showCount(state){
      return '当前最新的数据是【' + state.count + '】'
    }
  },
  modules: {}
});
复制代码
1.3.2 components文件夹下的Addition.vue
代码语言:javascript
复制
<template>
  <div>
      <!-- 也可以简写为$store.state.count -->
      <h3>当前最新的count值为:{{ this.$store.state.count }}</h3>
      <button @click="countAdd">1++</button>
      <button @click="countAdds">n++</button>
      <button @click="countAddActions">1++Action</button>
      <button @click="countAddsActions">n++Action</button>
      <!-- 使用计算属性显示count的值 -->
      <p>{{ $store.getters.showCount }}</p>
  </div>
</template>

<script>
    export default {
        data(){
            return{

            };
        },
        methods: {
            countAdd(){
                /*
                    不能这样写,如果state里的数据被修改了,并出现了报错
                    那么这时候去查错,就只能一个一个文件的去翻找是那个文件出现了错误
                    但如果使用mutations进行修改数据,那么数据出错时就只需要找它就行了
                    this.$store.state.count++;
                */
                //使用mutations方法调用;this.$store.commit("方法名")
                this.$store.commit('countAdd')
            },
            //以传参的方式进行添加
            countAdds(){
                //传入一个参数3,实现每次加3;this.$store.commit("方法名", 参数)
                this.$store.commit('countAdds', 3)
            },
            //使用异步操作;this.$store.dispatch('方法名')
            countAddActions(){
                this.$store.dispatch('countAddActions')
            },
            //异步传参;this.$store.dispatch('方法名', 参数)
            countAddsActions(){
                this.$store.dispatch('countAddsActions', 5)
            }
        }
    }
</script>
复制代码
1.3.3 components文件夹下的Subition.vue
代码语言:javascript
复制
<template>
  <div>
      <!-- 引用mapState后,只需要直接输入数据名就可引用了 -->
      <h3>当前最新的count值为:{{ count }}</h3>
      <button @click="btn1">1--</button>
      <button @click="btn2">n--</button>
      <button @click="countSubActions">1--Action</button>
      <button @click="countSubsActions">n--Action</button>
      <!-- 使用计算属性显示count的值 -->
      <p>{{ $store.getters.showCount }}</p>
  </div>
</template>

<script>

import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'

    export default {
        data(){
            return{

            }
        },
        computed: {
            //...表示展开运算符,把当前全局数据映射为计算属性
            ...mapState(['count']),
            //第二种引入Getters的方法
            ...mapGetters(['showCount'])
        },
        methods: {
            //把mutations映射到methods中
            ...mapMutations(['countSub','countSubs']),
            ...mapActions(['countSubActions','countSubsActions']),
            /*
                特别注意!!!如果是使用mapMutations方法引入的mutations方法
                其mutations里定义的方法名和methods定义的方法名不能相同!
                因为已经将mutations映射到methods中了,调用mutations的方法
                等同调用methods的方法;因为两个相同命名的方法被递归调用从而引发了报错
                Maximum call stack size exceeded
            */
            btn1(){
                //因为已经映射到methods中,从而可以直接调用方法
                this.countSub()
            },
            btn2(){
                this.countSubs(3)
            },
            //使用异步操作
            countSubActions(){
                this.$store.dispatch('countSubActions')
            },
            //异步传参
            countSubsActions(){
                this.$store.dispatch('countSubsActions', 5)
            }
        }
    }
</script>
复制代码

1.4 源码下载

未使用模块化的下载地址:📎vuex.zip

使用模块化并且mutations常量化命名的下载地址:📎vuex.zip

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Vue 脚手架中使用 Vuex
  • 在脚手架里进行Vuex开发:
    • 一、 使用Vuex实现跨组件修改数据
      • 1.1 效果页面预览
      • 1.2 Vuex的五个核心概念详解
      • 1.3 未使用模块化的详细代码
      • 1.4 源码下载
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档