vue2.x笔记11-Vuex

认识Vuex

Vuex是做什么的?

官方解释:Vuex是一个专为Vue.js应用程序开发的状态管理模式

  • 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

状态管理到底是什么?

  • 状态管理模式、集中式存储管理听起来难以理解
  • 其实就是将多个组件需要共享的变量全部存储在一个对象中
  • 然后将这个对象放在顶层的Vue实例中,让其他组件可以使用
  • Vuex就是提供一个在多个组件间共享状态的插件

管理什么状态

什么状态是需要多个组件间共享呢?

  • 在大型项目开发中,会遇到多个状态需要在多个界面间共享
  • 比如用户的登录状态、用户名称、头像等等
  • 比如商品的收藏、购物车中的物品等等
  • 这些状态,我们都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的

接下来,从实际的代码来看看状态管理

单界面的状态管理

在单个组件中进行状态管理是一件非常简单的事情

来看下面这张图片

  • State:就是我们的状态(暂时可以当做data中的属性)
  • View:视图层,可以针对State的变化,显示不同的信息
  • Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变

单界面状态管理的实现

  • 在这个案例中,counter需要某种方式被记录下来,也就是State
  • counter目前的值显示的界面中,也就是View部分
  • 界面发生某些操作时(这里时用户点击),需要去更新状态,也就是actions

多界面状态管理

在简单的多页面应用时,可以使用props来共享状态,如下图

如果多个界面都依赖同一个状态(一个状态改了,多个界面需要进行更新),或者不同界面的Actions都想修改同一个状态

这时候就需要交给大管家统一帮助管理,也就是Vuex

就可以使用Vuex

全局单例模式(大管家)

  • 现在要做的就是将共享的状态抽取出来,交给大管家,统一进行管理
  • 之后,每个视图按照规定好的规定,进行访问和修改等操作
  • 这就是Vuex背后的基本思想

Vuex状态管理图例

Vuex的基本使用

安装Vuex插件(vue2.x版本需要安装vuex3.x版本)

npm install vuex@3.5.1 --save

在src文件夹下创建store文件夹,创建index.js文件

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex)

const store = new Vuex.Store({
  state:{
    counter: 100
  },
  mutations:{
    increment(state) {
      state.counter++
    },
    decrement(state) {
      state.counter--
    }
  },
  getters: {},
  actions: {},
  modules: {}
})

export default store

到main.js文件,导入store对象,并挂载到Vue实例中

修改App.vue文件,使用Vuex的counter

<template>
  <div id="app">
    <h2>-------APP组件内容-------</h2>
    <h2>{{$store.state.counter}}</h2>
    <button @click="addition">+</button>
    <button @click="subtraction">-</button>

    <h2>-------HelloVuex组件内容-------</h2>
    <hello-vuex />
  </div>
</template>

<script>
import HelloVuex from "./components/HelloVuex.vue";
export default {
  name: 'App',
  components: {
    HelloVuex
  },
  methods: {
    addition() {
      this.$store.commit('increment')
    },
    subtraction() {
      this.$store.commit('decrement')
    }
  }
}
</script>

<style>
</style>

修改HelloVuex.vue文件内容

步骤小结:

  1. 提取出一个公共的store对象,用于保存在多个组件中共享状态
  2. 将store对象挂载到Vue实例中,这样可以保证所有组件都可以使用
  3. 在其他组件中使用store对象中保存的状态
    • 通过this.$store.state.属性的方式来访问状态
    • 通过this.$store.commit('mutations中的方法')来修改状态

注意事项:

  • 通过提交mutation的方式,而非直接改变store.state.counter
  • 这是因为Vuex可以明确的追踪状态的变化,所以不要直接改变store.state.counter的值

 浏览器安装Vue.js devtools扩展程序

右键检查,找到Vue,即可追踪状态变化

Vuex的核心概念

Vuex有几个比较核心的概念:

State、Getter、Mutation、Action、Module

State单一状态树

Vuex提出使用单一状态树,那什么是单一状态树呢?

        英文名称是Single Source of Truth,也可以翻译成单一数据源

举个生活中的例子

  • 在国内我们的很多信息需要被记录,比如个人档案、社保记录、公积金记录、户口信息、医疗信息等
  • 这些信息别分散在各个地方进行管理,如果某天需要办理业务,会发现我们需要到各个对应的工作地点去打印、盖章各种资料,最后到一个地方提交证明
  • 这种保存信息的方案,不仅低效,还不方便管理

这个与应用开发中比较类似

  • 如果状态信息保存到多个store对象中,那么之后的管理和维护都会变得困难
  • 所以Vuex使用了单一状态树来管理应用层级的全部状态
  • 单一状态树能够以最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也会方便管理和维护

Getter

Getter基本使用

有时候,需要从store中获取一些state变异后的状态,比如获取年龄大于20的学生信息

创建学生信息

在store中定义getters

在App.vue中使用

Getter作为参数和传递参数

1.已经获取了年龄大于20的学生信息,再显示超过20的学生数量

getters作为参数使用

App.vue中修改

2.超过自定义年龄的学生信息(getters默认不能传递参数,如果希望传参,只能让getters本身返回另一个函数)

getters内容

App.vue

Mutation

Mutation状态更新

Vuex的store状态的更新唯一方式:提交Mutation

Mutation主要包括两部分

  • 字符串的事件类型(type)
  • 一个回调函数(handler),该回调函数的第一个参数就是state

mutation的基本使用:

Mutation传递参数

通过mutation更新数据时,可能需要传递额外的参数

        参数被称为mutation的载荷(Payload)

比如之前的计数增加特定的数量

如果参数不是一个呢?

  • 比如有多个参数需要传递
  • 这个时候,我们通常会以对象的形式传递,也就是payload是一个对象
  • 然后再从对象中取出相关的信息

Mutation提交风格

通过commit进行提交是一种普通的方式

Vue还提供了另外一种风格, 它是一个包含type属性的对象(mutations中的处理方式是将整个commit的对象作为payload使用,所以代码不需要改变)

Mutation响应规则

Vuex的store中state是响应式的,当state中的数据发生改变时,Vue组件会自动更新

这就要求我们要遵守一些Vuex对应的规则:

  • 提前在store中初始化好所需的属性
  • 当给state中的对象添加新属性时,使用下面的方式:
    • 方式一:使用Vue.set(obj, 'newProp',123)
    • 方式二:用新的对象给旧的对象重新赋值
  • 当给state中的对象删除属性时,使用Vue.delete(obj, 'prop')

Mutation常量类型

在mutation中,定义了很多事件类型(也就是其中的方法名称),在项目增大时,管理的状态越来越多,需要更新的也就越来越多,方法过多,就需要花大量的精力去记,或者多个文件间来回切换,如果不复制,还有可能出现写错的情况

如何避免上面的问题呢?

  • 在各种Flux实现中,一种很常见的方案就是使用常量替代Mutation事件的类型
  • 可以将这些常量放在一个单独的文件中,方便管理以及让整个app所有事件类型一目了然

怎么做呢?

  • 创建一个文件:mutation-types.js,并在其中定义常量
  • 定义常量时,可以使用ES2015中的风格,使用常量作为函数的名称

Mutation同步函数

通常情况下,Vuex要求Mutation中的方法必须是同步方法

  • 主要的原因是当使用devtools时,devtools可以帮助捕捉mutation的快照
  • 但如果异步操作,devtools就不能很好的追踪这个操作什么时候会被完成

比如之前的修改个人信息的代码,改为异步函数后

会发现state中info的数据一直没改变,因为他无法追踪到

所以,通常情况下,不要在mutation中进行异步操作

Action

Action的基本定义

不要在mutation中进行异步操作,但某些情况,确实希望在Vuex中进行一些异步操作,比如网络请求,异步的需要怎么处理呢?

Action类似于Mutation,但是用来代替Mutation进行异步操作的

Action的基本使用

context是什么?

  • context是和store对象具有相同方法和属性的对象
  • 也就是说,可以通过context去commit,也可以获取context.state等
  • 但是它们并不是同一个对象,下面学到Modules时再说

action也可以传递参数

Action返回的Promise

在ES6语法中,Promise经常用于异步操作

Promise的使用_notChange的博客-CSDN博客本文主要包括:什么是Promise、Promise的基本使用、链式调用、all方法使用https://blog.csdn.net/notChange/article/details/123326984?spm=1001.2014.3001.5501在action中,可以将异步操作放在一个Promise中,并且在成功或失败后,调用对应的resolve或reject

Module

认识Module

Module是模块的意思,为什么在Vuex中使用模块呢?

  • Vue使用单一状态树,也就意味着很多状态都会交给Vuex来管理
  • 当应用变得非常复杂是,store对象就有可能变得很臃肿
  • 为了解决这个问题,Vuex允许将store分隔成模块(Module),而每个模块拥有自己的state、mutations、actions、getters等
const moduleA = {
  state: {},
  mutations: {},
  actions: {},
  getters: {}
}

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

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

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

Module局部状态

具体的局部模块代码编写

mutations和getters接收的第一个参数是局部状态对象

注意:虽然updateName和fullName都是定义在对象内部的,但在调用的时候,还是通过this.$store来直接调用

Actions的写法

actions接收一个context参数对象,包含自身的store对象,也包含根节点的,获取根节点状态:context.rootState

getters中也可以接收更多的参数

项目结构组织

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值