前言

  vuex作为vue的核心插件,同时在开发中也是必不可少的基础模块,本文来总结一下相关知识点。

正文

  1、基于单向数据流问题而产生了Vuex

  单向数据流是vue 中父子组件的核心概念,props 是单向绑定的。当父组件的属性值发生变化的时候,会传递给子组件发生相应的变化,从而形成一个单向下行的绑定,父组件的属性改变会流向下行子组件中,但是反之,为了防止子组件无意间修改了父组件中的数据而影响到了其他的子组件的状态,vue 规定了从下往上的数据流是不允许的。当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

a、多个组件依赖于同一状态。组件之间传参变得特别繁琐,并且兄弟组件之间状态传递无能为力。

b、来自不同视图的行为需要变更同一状态。 经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。

  我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

  使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。应该根据你的应用开发需要进行权衡和确定。

  2、安装及使用

  1. CDN 方式: <script src="...vuex.js"></script>
  2. NPM 方式: npm install vuex --save
  3. Yarn方式: yarn add vuex
  4. 其他方式:项目初始化是引入依赖
  5. 无论哪种方式都需要 Vue.use(Vuex)来安装 Vuex

  3、核心及使用方法

  每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 vuex的Vuex 核心 State 、Getters 、Mutation、  Action、  Module。

  (1)State

  Vuex也使用了单一状态树来管理应用层级的全部状态。唯一数据源。

  单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。

  state存储状态类似于组件中data,在组件中访问状态经常有两种方法:分别为

    a、通过 this.$store.state.属性 的方式来访问状态,通常写在computed计算属性中,当然也可以直接通过插值表达式访问;

    b、借助mapState 辅助函数。

  核心代码如下:

  1. <div id="app">
  2. {{ mycount }}<br>
  3. 直接插值表达式访问
  4. {{ this.$store.state.count }}<br>
  5. {{ myinfoAge }}<br>
  6. </div>
  7. <script>
  8. import Vue from 'vue';
  9. import Vuex from 'vuex';
  10. import { mapState } from 'vuex'// 使用辅助函数一定记住引入
  11. const store = new Vuex.Store({
  12. // 存储状态数据
  13. state: {
  14. count: 0,
  15. info:{
  16. name:"xiaoming",
  17. age:18
  18. }
  19. },
  20. )
  21. new Vue({
  22. el: '#app',
  23. store,
  24. computed:{
  25. // a、计算属性方式
  26. mycount(){
  27. return this.$store.state.count
  28. },
  29. // b、利用辅助函数赋值给对应变量,页面可以直接使用该变量
  30. ...mapState({
  31. myinfoAge: (state) => state.info.age,
  32. }),
  33. // 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。下面的简化写法相当于 info: (state) => state.info,
  34. ...mapState(["info"]),
  35. }
  36. })
  37. </script>

  (2) Getters

  store的一个计算属性,类比组件的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,Getter 接受 state 作为其第一个参数,在state中的数据发生改变,计算属性重新计算

  Getters 的状态存储相当于组件中计算属性,访问方式有三种:

    a、通过属性访问

    b、通过方法访问

    c、通过mapGetters 辅助函数访问

  核心代码如下:

  1. <div id="app">
  2. {{ myInfoLength }}<br>
  3. 直接插值表达式访问
  4. {{ this.$store.getters.infoLength }}<br>
  5. {{ myName }}<br>
  6. {{ infoLength }}
  7. </div>
  8. <script>
  9. import Vue from 'vue';
  10. import Vuex from 'vuex';
  11. import { mapGetters } from 'vuex'// 使用辅助函数一定记住引入
  12. const store = new Vuex.Store({
  13. state: {
  14. info:[
  15. {name:"name1",age:18},
  16. {name:"name2",age:28}
  17. ]
  18. },
  19. // 存储状态数据
  20. getters: {
  21. infoLength: (state) => {
  22. return state.info.length;
  23. },
  24. getNameByAge: (state) => (age) => {
  25. return state.info.find(item => item.age === age).name
  26. }
  27. },
  28. )
  29. new Vue({
  30. el: '#app',
  31. store,
  32. computed:{
  33. // a、通过属性访问
  34. myInfoLength(){
  35. return this.$store.getters.infoLength
  36. }
  37. // b、通过方法访问
  38. myName(){
  39. return this.$store.getters.getNameByAge(18)
  40. }
  41. // c、mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
  42. ...mapGetters(["infoLength"])
  43. }
  44. })
  45. </script>

  (3) Mutation

  前面state和getters两个核心概念都是为了在store存储数据和访问数据的使用,Mutation则提供了对store中数据的修改功能,并且是唯一的更新方式,提交Mutation,Mutation主要包括两部分:字符串的事件类型(type)和一个回调函数(handler),该回调函数的第一个参数就是state。

  在视图组件中不能直接修改store容器中的状态,需要先在容器中注册一个事件函数,当需要更新状态时候需要提交触发该事件,同时可以向该事件传递参数。这里需要区别与组件内v-model双向绑定。提交事件方法有一下几种:

    a、普通提交方式

    b、对象风格提交

    c、借助 mapMutations 辅助函数

  其核心代码如下:

  1. <div id="app">
  2. <button @click="handleAdd">点我加一</button>
  3. <button @click="handleAddForNum">点我加加</button>
  4. <button @click="handleAddForObj">对象添加</button>
  5. <button @click="handleAddMap">对象添加</button>
  6. </div>
  7. <script>
  8. import Vue from 'vue';
  9. import Vuex from 'vuex';
  10. import { mapMutations } from 'vuex'// 使用辅助函数一定记住引入
  11. const store = new Vuex.Store({
  12. state: {
  13. count:1
  14. },
  15. mutations:{
  16. // 注册事件
  17. addCount(state){
  18. state.count ++
  19. },
  20. addCountForNum(state,num){
  21. state.count += num
  22. },
  23. addCountForObj(state,payload){
  24. state.count += payload.num
  25. },
  26. addMap(state){
  27. state.count ++
  28. }
  29. }
  30. )
  31. new Vue({
  32. el: '#app',
  33. store,
  34. methods:{
  35. // a、普通提交方式
  36. handleAdd(){
  37. this.$store.commit('addCount')
  38. },
  39. handleAddForNum(){
  40. this.$store.commit('addCountForNum',10)
  41. },
  42. // b、对象风格提交
  43. handleAddForObj() {
  44. this.$store.commit({ type: "addCountForObj", num: 100 });
  45. },
  46. // c、借助 mapMutations 辅助函数
  47. ...mapMutations(["addMap"]),
  48. handleAddMap(){
  49. this.addMap()
  50. }
  51. }
  52. })
  53. </script>

  Mutation 需遵守 Vue 的响应规则,Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:最好提前在你的 store 中初始化好所有所需属性。当需要在对象上添加新属性时,你应该使用 Vue.set(obj, 'newProp', 123), 或者以新对象替换老对象。例如,利用对象展开运算符 state.obj = { ...state.obj, newProp: 123 }

注意:Mutation 必须是同步函数。在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?

(4) Action

Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.action 用于异步的修改state,它是通过muation间接修改state的。

context是和store对象具有相同方法和属性的对象.也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等.

若需要异步操作来修改state中的状态,首先需要action来注册事件,组件视图在通过dispatch分发方式调用该事件,该事件内部提交mutation中的事件完成改变状态操作,总之,通过action这个中介来提交mutation中的事件函数.分发事件方法如下:

  a、普通提交方式

   b、对象风格提交

  c、借助 mapActions 辅助函数

核心代码如下:

  1. <div id="app">
  2. <button @click="handleAdd">点我加一</button>
  3. <button @click="handleAddTen">点我加十</button>
  4. <button @click="handleAddForObj">对象添加</button>
  5. <button @click="handleAddMap">对象添加</button>
  6. </div>
  7. <script>
  8. import Vue from 'vue';
  9. import Vuex from 'vuex';
  10. import { mapMutations,mapActions } from 'vuex'// 使用辅助函数一定记住引入
  11. const store = new Vuex.Store({
  12. state: {
  13. count:1
  14. },
  15. // 注册事件修改state状态值
  16. mutations:{
  17. addCount(state){
  18. state.count ++
  19. },
  20. addCountForNum(state,num){
  21. state.count += num
  22. },
  23. addCountForObj(state,payload){
  24. state.count += payload.num
  25. },
  26. addMap(state){
  27. state.count ++
  28. }
  29. },
  30. // 注册事件,提交给 mutation
  31. actions:{
  32. addAction(context){
  33. setTimeout(() => {
  34. context.commit('addCount')
  35. }, 1000)
  36. },
  37. addActionForNum(context,num){
  38. setTimeout(() => {
  39. context.commit('addCountForNum',num)
  40. }, 1000)
  41. },
  42. addActionForObj(context,payload){
  43. setTimeout(() => {
  44. context.commit('addCountForObj',payload)
  45. }, 1000)
  46. },
  47. addActionMap(context){
  48. setTimeout(() => {
  49. context.commit('addMap')
  50. }, 1000)
  51. }
  52. }
  53. )
  54. new Vue({
  55. el: '#app',
  56. store,
  57. methods:{
  58. // a、普通提交方式
  59. handleAdd(){
  60. this.$store.dispatch('addAction')
  61. },
  62. handleAddTen(){
  63. this.$store.dispatch('addActionForNum',10)
  64. },
  65. // b、对象风格提交
  66. handleAddForObj(){
  67. this.$store.dispatch({
  68. type: 'addActionForObj',
  69. amount: 10
  70. })
  71. }
  72. // 借助 mapActions 辅助函数
  73. ...mapActions(["addActionMap"]),// 相当于...mapActions({addActionMap:"addActionMap"})
  74. handleAddMap(){
  75. this.addActionMap()
  76. }
  77. }
  78. })

  组合 Action:组合多个 action,以处理更加复杂的异步流程.store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise。一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。假设 getData() 和 getOtherData() 返回的是 Promise。

  1. actions: {
  2. async actionA ({ commit }) {
  3. commit('gotData', await getData())
  4. },
  5. async actionB ({ dispatch, commit }) {
  6. await dispatch('actionA') // 等待 actionA 完成
  7. commit('gotOtherData', await getOtherData())
  8. }
  9. }

  (5)Modules

  Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等

4、Vuex和全局对象的不同

  (1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  (2)你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

写在最后

  以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长之路会持续更新一些工作中常见的问题和技术点。

vue--vuex 状态管理模式的更多相关文章

  1. 了解Vuex状态管理模式的理解强化指南

    1 Vuex是什么呢?它是Vue的状态管理模式,在使用vue的时候,需要在vue中各个组件之间传递值是很痛苦的,在vue中我们可以使用vuex来保存我们需要管理的状态值,值一旦被改变,所有引用该值的地 ...

  2. 转 理解vuex -- vue的状态管理模式

    转自:https://segmentfault.com/a/1190000012015742 vuex是什么? 先引用vuex官网的话: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 ...

  3. vuex -- vue的状态管理模式

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 状态管理模式.集中式存储管理 一听就很高大 ...

  4. 理解Vue的状态管理模式Vuex

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 状态管理模式.集中式存储管理,一听就很高大 ...

  5. Vue.js状态管理模式 Vuex

    vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 安装.使用 vuex 首先我们在 vue. ...

  6. Vuex 状态管理模式

    Vuex 是一个专为 Vue.js 设计的状态管理模式 vuex解决了组件之间同一状态的共享问题.当我们的应用遇到多个组件共享状态时,会需要: 多个组件依赖于同一状态.传参的方法对于多层嵌套的组件将会 ...

  7. Vuex状态管理模式的面试题及答案

    转载:点击查看原文 1.vuex有哪几种属性? 答:有五种,分别是 State. Getter.Mutation .Action. Module 2.vuex的State特性是? 答: 一.Vuex就 ...

  8. 关于vuex状态管理模式架构

    一. 什么是vuex 集中存储管理所有组件的状态 并以相应的规则保证以一种可预测的方式发生变化. 例子: 实现加减 <p>{{count}} <button @click=" ...

  9. Vuex状态管理模式

    Store:类似容器,包含应用的大部分状态,一个页面只能有一个store,状态存储是响应式的 State : 包含所有应用级别状态的对象 Getters : 在组件内部获取store中状态的函数 Mu ...

  10. 五、vue状态管理模式vuex

    一.vuex介绍 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 即data中属性同时有一 ...

随机推荐

  1. Linux环境下安装Maven

    最近在搞虚拟机,记录下虚拟机内Maven环境的搭建流程 一.选择合适的版本(由于Maven运行需要依赖于JDK,所以安装之前需要保证当前虚拟机下已经安装并配置好JDK环境,安装流程参见) https: ...

  2. Mysql数据库索引的使用

    1.索引的使用 查询 表的锁show index from qk_auth_employee 2.走索引 EXPLAIN SELECT * from qk_auth_employee where Da ...

  3. 网络监听HTTP协议信息实验

    一.开启环境 登录web服务器,在服务器中开启phpstudy服务器环境. 在操作机中打开目标站[Web服务器IP地址]地址.安装wordpress,数据库名:wordpress,用户名root 密码 ...

  4. STL基本用法的一些记录

    迭代器 (set类型)::iterator 就是迭代器 迭代器可以看成stl容器内元素的指针 set 默认从小到大排序 begin() set中最小的元素的迭代器 end() set中最大的元素的迭代 ...

  5. 论文翻译:2018_Source localization using deep neural networks in a shallow water environment

    论文地址:https://asa.scitation.org/doi/abs/10.1121/1.5036725 深度神经网络在浅水环境中的源定位 摘要: 深度神经网络(DNNs)在表征复杂的非线性关 ...

  6. C++ TCHAR* 与char* 互转

    C++ TCHAR* 与char* 互转 在MSDN中有这么一段: Note: The ANSI code pages can be different on different computers, ...

  7. Xshell 连接虚拟机OS Linux 设置静态ip ,网络配置中无VmWare8 的解决办法

    前序:最近开始研究Hadoop平台的搭建,故在本机上安装了VMware workstation pro,并创建了Linux虚拟机(centos系统),为了方便本机和虚拟机间的切换,准备使用Xshell ...

  8. 发现程序美----while+for冒泡实现的

    思想记录: 每一轮回的冒泡都将产生一个最大值,其后每次循环次数都将少一次,因为每次都会确定一个最大值. private void method(){ int[] list = {10,7,8,4,7, ...

  9. JDBC的全称是什么?

    Java DataBase Connectivity,java数据库连接

  10. mybatis基础(全)

    参考链接:Mybatis学习系列(一)入门简介 Mybatis学习系列(二)Mapper映射文件 Mybatis学习系列(三)动态SQL Mybatis学习系列(四)Mapper接口动态代理 Myba ...