Vuex的五个核心属性

2023-11-17

Vuex的五个核心概念

本文参考自Vue文档,说的非常详细,建议看文档。

Vuex是什么?

VueX 是一个专门为 Vue.js 应用设计的状态管理架构,统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data )。

Vue有五个核心概念,state, getters, mutations, actions, modules。本文将对这个五个核心概念进行梳理。

总结

state => 基本数据
getters => 从基本数据派生的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex

State

state即Vuex中的基本数据!

单一状态树

Vuex使用单一状态树,即用一个对象就包含了全部的状态数据。state作为构造器选项,定义了所有我们需要的基本状态参数。

在Vue组件中获得Vuex属性

  • 我们可以通过Vue的Computed获得Vuex的state,如下:
const store = new Vuex.Store({
    state: {
        count:0
    }
})
const app = new Vue({
    //..
    store,
    computed: {
        count: function(){
            return this.$store.state.count
        }
    },
    //..
})

每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

mapState辅助函数

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 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
    }
  })
}

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

对象展开运算符

mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。但是自从有了对象展开运算符,我们可以极大地简化写法:

computed: {
  localComputed () //本地计算属性
  //使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    //..
  })
}
  • 对象运算符
    ... 展开运算符(spread operator)允许一个表达式在某处展开。展开运算符在多个参数(用于函数调用)或多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方可以使用。

    展开运算符不能用在对象当中,因为目前展开运算符只能在可遍历对象(iterables)可用。iterables的实现是依靠[Symbol.iterator]函数,而目前只有Array,Set,String内置[Symbol.iterator]方法,而Object尚未内置该方法,因此无法使用展开运算符。不过ES7草案当中已经加入了对象展开运算符特性。

    例子:

    function test(a,b,c) {
        console.log(a);
        console.log(b);
        console.log(c);
    }
    var args = [0,1,2];
    test(...args);  // 0  1  2
  • ES7草案中的对象展开运算符
    ES6中还不支持对对象的展开运算符,但是ES7中将支持。对象展开运算符符可以让我们更快捷地操作对象,如下例子:
    let {x,y,...z}={x:1,y:2,a:3,b:4};
    x; //1
    y; //2
    z; //{a:3,b:4}

组件仍然保有局部状态

使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。

如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。

getters

即从store的state中派生出的状态。

getters接收state作为其第一个参数,接受其他 getters 作为第二个参数,如不需要,第二个参数可以省略如下例子:

const store = new Vuex.Store({
    state: {
        count:0
    },
    getters: {
        // 单个参数
        countDouble: function(state){
            return state.count * 2
        },
        // 两个参数
        countDoubleAndDouble: function(state, getters) {
            return getters.countDouble * 2
        }
    }
})

与state一样,我们也可以通过Vue的Computed获得Vuex的getters。

const app = new Vue({
    //..
    store,
    computed: {
        count: function(){
            return this.$store.state.count
        },
        countDouble: function(){
            return this.$store.getters.countDouble
        },
        countDoubleAndDouble: function(){
            return this.$store.getters.countDoubleAndDouble
        }
    },
    //..
})

mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性,与state类似

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getters 混入 computed 对象中
    ...mapGetters([
      'countDouble',
      'CountDoubleAndDouble',
      //..
    ])
  }
}

如果你想将一个 getter 属性另取一个名字,使用对象形式:

mapGetters({
  // 映射 this.double 为 store.getters.countDouble
  double: 'countDouble'
})

mutations

提交mutation是更改Vuex中的store中的状态的唯一方法。

mutation必须是同步的,如果要异步需要使用action。

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    //无提交荷载
    increment(state) {
        state.count++
    }
    //提交荷载
    incrementN(state, obj) {
      state.count += obj.n
    }
  }
})

你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

//无提交荷载
store.commit('increment')
//提交荷载
store.commit('incrementN', {
    n: 100
    })

对象风格的提交方式

我们也可以使用这样包含 type 属性的对象的提交方式。

store.commit({
  type: 'incrementN',
  n: 10
})

Mutations 需遵守 Vue 的响应规则

  • 最好提前在你的 store 中初始化好所有所需属性。
  • 当需要在对象上添加新属性时,你应该
    • 使用 Vue.set(obj, 'newProp', 123), 或者
    • 以新对象替换老对象。例如,利用对象展开运算符我们可以这样写state.obj = {...state.obj, newProp: 123 }

mapMutations 辅助函数

与其他辅助函数类似,你可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

import { mapMutations } from 'vuex'

export default {
  //..
  methods: {
    ...mapMutations([
      'increment' // 映射 this.increment() 为 this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
    })
  }
}

actions

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

我们用如下例子来结束actions:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      setInterval(function(){
        context.commit('increment')
      }, 1000)
    }
  }
})

注意:Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

分发actions

Action 通过 store.dispatch 方法触发:

store.dispatch('increment')

其他与mutations类似的地方

Actions 支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发
store.dispatch('incrementN', {
  n: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementN',
  n: 10
})

mapActions辅助函数

你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):

import { mapActions } from 'vuex'

export default {
  //..
  methods: {
    ...mapActions([
      'incrementN' //映射 this.incrementN() 为 this.$store.dispatch('incrementN')
    ]),
    ...mapActions({
      add: 'incrementN' //映射 this.add() 为 this.$store.dispatch('incrementN')
    })
  }
}

Modules

使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。

为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

模块的局部状态

对于模块内部的 mutationgetter,接收的第一个参数是模块的局部状态,对于模块内部的 getter,根节点状态会作为第三个参数:

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // state 模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    },
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

同样,对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum (context) {
      if ((context.state.count + context.rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vuex的五个核心属性 的相关文章

  • 使用 Vuex 4 时,Vue.js 2 中出现警告

    当我尝试在 Vue 2 中使用 Vuex 4 作为商店时 控制台中出现警告 我该如何解决它 在 vue 中找不到导出 注入 反应 监视 以下是package jsonVue v2 x 和 Vuex v4 x 的条目 store js imp
  • 多个 Vue 实例需要多个 Vuex 模块实例

    我正在将 Vue 集成到表单网站上 这意味着如果页面上有多个表单 我必须创建该 Vue 应用程序的多个实例 所有实例共享同一个 Vuex 存储 我创建了一个 Vuex 模块 以便每个 Vue 实例都可以拥有自己的本地状态 我的主要目标是防止
  • Nuxt.js:开始从 vuex 加载指示器

    根据文档 有一种方法可以在组件中手动启动 nuxt 加载指示器 如下所示 export default methods startLoading this root loading start 有没有办法从 vuex 操作切换加载器 我怎样
  • vue合成api如何解决命名冲突?

    据说composition api解决了mixin带来的命名冲突 这是我在网上找到的关于composition API的内容 export default setup const someVar1 someMethod1 useCompFu
  • Vuex Store 模块访问状态

    我想知道如何从另一个文件访问模块存储 状态 到目前为止 这是我的代码 store index js import Vuex from vuex import categories from modules categories Vue us
  • 创建 Vuex 存储后,如何手动将 getter/mutations 添加到 Vuex 存储中?

    我正在尝试在我的 Vuejs 组件之一的 created 生命周期挂钩中添加新变量 getter 和突变 变量工作正常 但对于 getters mutations 来说 似乎并不像向 vuex 存储对象添加新函数那么容易 我试图解决的问题是
  • 带 setter 的 mapState

    我想通过分配setter方法mapState 我目前使用一种解决方法 命名我感兴趣的变量 todo 作为临时名称 storetodo 然后在另一个计算变量中引用它todo methods mapMutations clearTodo upd
  • Vue.js/vuex ajax 使用 ajax 状态更新组件

    我将 vue webpack 模板与 vuex 一起使用 基本上遇到组件不随状态更新的问题 我有一家商店 const state userData 在我的应用程序中我有一个方法 methods addUserData function co
  • Vuex getter 未更新

    我有以下吸气剂 withEarmarks state gt var count 0 for let l of state laptops if l earmarks length gt 0 count return count 在组件中 这
  • Vuex axios调用无法处理422响应

    我正在尝试处理来自 API 的 422 响应 以防在进行异步 Axios 调用时数据无效 在组件中 我有一个类似的方法 async saveChanges this isSaving true await this store dispat
  • 如何在Vuex中深度克隆状态并回滚?

    在 Vuex 中 我想拍摄树中对象属性的快照 克隆 修改它 然后可能回滚到以前的快照 背景 在应用程序中 用户可以在应用某些更改之前尝试它们 应用更改时 它们应该影响主 vuex 树 用户还可以单击 取消 放弃更改并返回到之前的状态 Exa
  • vuex 未加载用 vuex-module-decorators 装饰的模块

    当尝试将带有 vuex module decorators 的存储模块加载到初始化程序中时 我收到此错误 vuex esm js 2f62 261 未捕获类型错误 无法读取属性 Array forEach 的 eval vuex esm j
  • Vue router - 如何根据用户角色在同一路由路径上加载多个组件?

    我有一个应用程序 用户可以以不同的角色登录 例如 seller buyer and admin 对于每个用户 我想在同一路径上显示仪表板页面 例如 http localhost 8080 dashboard然而 每个用户将在不同的 vue
  • Vuex - 绑定助手中的动态命名空间(mapState,...)

    我正在动态注册 vuex 存储模块 store registerModule home grid GridStore 然后在组件中 export default name GridComponent props namespace type
  • Vuex 动作与突变

    在Vuex中 同时拥有 动作 和 变异 的逻辑是什么 我理解组件无法修改状态的逻辑 这看起来很聪明 但是同时具有操作和突变似乎您正在编写一个函数来触发另一个函数 然后更改状态 动作 和 突变 之间有什么区别 它们如何协同工作 而且我很好奇为
  • Vue Axios 动态 URL

    我想在 vue js 应用程序中动态创建 axios post 操作的 URL 路径 这是动作 editProduct function dispatch commit payload axios put http localhost 80
  • 无法访问 Axios 拦截器内的 Vuex 存储突变

    EDIT 这个问题非常混乱 所以我基本上用相同的代码示例和相同的场景重写它 当服务器发送 401 错误响应时 我试图 commit从拦截器到我的 vuex 存储 import axios from axios import store fr
  • 在Vuex模块中进行继承的方法

    我使用 VueJS 和 Vuex 构建我的应用程序 当我有多个模块使用相同的数据字段时 我遇到了这个问题 它是关于像 dat 这样的 API 配置 getUsers state commit axios get urls API USER
  • Vue.use() 抛出“无法读取未定义的属性‘use’”

    尝试1 main js import createApp from vue import store from store store import App from App vue Vue config productionTip fal
  • 来自 VueX 和 NuxtJS 的持久状态

    我使用 vuex persistedstate 包 https github com robinvdvleuten vuex persistedstate https github com robinvdvleuten vuex persi

随机推荐

  • 浅谈年轻人低存款状态与面临的困难

    目前 我的存款处于一万元以上的区间 对于我个人而言 存款并不是一件太过困难的事情 我秉持着理财的原则 通过合理的规划和节制开支 我能够将一部分收入用于存款 同时 我也会尽量避免不必要的消费 以确保有足够的资金用于应急和未来的规划 我相信 理
  • maven打包内存溢出,或者打包时间太长导致未知错误

    在idea中使用maven打包内存溢出问题 qq 27607447的博客 CSDN博客
  • numpy常用函数(一元通用函数、二元通用函数列表)

    Numpy通用函数 也可以称为ufunc 是一种在ndarray数据中进行逐个元素操作的函数 某些简单函数接受一个或多个标量数值 并产生一个或多个标量结果 而通用函数就是对这样简单函数的向量化封装 1 一元通用函数 比如sqrt或exp举例
  • 淘宝图片轮播代码

    下面图片轮播代码中 ul class lst main 与 ul 之间的代码为用户可以自定义修改的部分 为轮播的图片地址和超级连接地址信息 li a href http mb2 yubaibai com cn 201011 30 90221
  • String类常用方法系列八:替换

    1 String replace target value 替换指定字符 Test public void test1 String str 好好学习 天天向上 我爱学习 str str replace 好好学习 System out pr
  • 基于java-agent的监控

    jolokia是一个基于java agent的监控
  • UUID工具类

    import java util UUID public class Uuid public static String id32 String uuid UUID randomUUID toString uuid uuid replace
  • ehvierwer登录与不登录_《天涯明月刀手游》pc端手机端登录不进去如何解决 服务器已满快速解决方法...

    导读 天涯明月刀这款手游终于公测了 每个玩家都可以在这里创造属于自己的江湖世界 不同的人会有不同的旅程 所以想要拥有一段属于自己江湖旅程就一定不要错过天刀这款手游 不过这款游戏刚公测 有很多bug 不知道怎 天涯明月刀这款手游终于公测了 每
  • 机器语言->汇编语言->高级语言

    在硬件层面来看 计算机的运行就是高底电压的变化 这种高低电压的变化在早期是通过开关或插拔电线来控制的 计算机中用0和1来表示低电压和高电压 这些0和1的序列就可以控制计算机CPU进行各种动作 一组一组的0 1序列就是一个一个的指令 这些指令
  • springboot的日志管理

    springboot的默认日志管理 SprongBoot使用的默认日志框架是Logback 并用INFO级别输出到控制台 SpringBoot的日志的级别有7个 TRACE DEBUG INFO WARN ERROR FATAL OFF 日
  • SAP创建采购申请的时候供货源信息不完整

    如图所示 原先该物料的对应的供应商的采购信息记录已经维护好 货源清单也已经创建 但是在ME51N创建采购申请的时候发现红色框的供应商是没显示出来的 首先检查货源清单ME01 数据维护完整 然后返回到ME11采购信息记录中发现 有必填项没有维
  • 【华为OD机试】最少面试官数 (C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 题目描述 某公司组织一场公开招聘活动 假设由于人数和场地的限制 每人每次面试的时长不等 并已经安排给定
  • Layui框架的拖动上传 以及 时间选择器的基本使用

    上传用的layui的点击or拖动上传 其他上传也同理 不喜勿喷 欢迎补充 上代码 html div class layui form item style width 1 div
  • 使用代码下载开源的大模型文件示例以及中文微调llama资源汇总:

    一 下载示例 from huggingface hub import snapshot download repo id THUDM chatglm2 6b local dir chatglm2 6b cache dir local dir
  • 微信小程序 navigationStyle custom 无效

    因为项目风格要求 需要自定义导航栏 所以需要将默认的导航栏隐藏掉 隐藏的代码 倒很简单 只需要在相应的页面json文件中添加以下代码即可 navigationStyle custom 然后问题出来了 因为产品太多 需要将A产品的部分页面移植
  • 模拟电路设计(8)--- 耗尽型MOSFET

    上篇我们讲到增强型MOSFET的特点是 N沟道的建立是Ugs的贡献 没有Ugs gt Ut 导电沟道就无法建立 D S就不会有导通电流 这边我们要说的是另一种MOSFET 称为耗尽型MOSFET N沟道耗尽型MOSFET结构示意图 以N沟道
  • java并发编程笔记(三)--管程(二)

    习题 卖票 请改正 public class ExerciseSell public static void main String args 2000张票 TicketWindow ticketWindow new TicketWindo
  • Redis - WRONGTYPE Operation against a key holding the wrong kind of value

    用RedisTemplate把数据存入Redis key值为物料编码 value值为对应对象 但相同物料编码对应的对象不一定唯一故采用Set for int i 0 i lt retrospectiveBomSbomtList size i
  • 分布式系统的一致性级别划分及Zookeeper一致性级别分析

    最近在研究分布式系统的一些理论概念 例如关于分布式系统一致性的讨论 看了一些文章我有一些不解 大多数对分布式系统一致性的划分是将其分为三类 强一致性 顺序一致性以及弱一致性 强一致性 Strict Consistency 也称为 原子一致性
  • Vuex的五个核心属性

    Vuex的五个核心概念 本文参考自Vue文档 说的非常详细 建议看文档 Vuex是什么 VueX 是一个专门为 Vue js 应用设计的状态管理架构 统一管理和维护各个vue组件的可变化状态 你可以理解成 vue 组件里的某些 data V