Vuex详细使用说明-一篇文章涵盖所有知识点(上)

简介: Vuex详细使用说明-一篇文章涵盖所有知识点(上)

一. 前言



不管是Vue,还是 React,都需要管理状态(state),比如组件之间都有共享状态的需要。


什么是共享状态? 比如一个组件需要使用另一个组件的状态,或者一个组件需要改变另一个组件的状态,都是共享状态。


如果不对状态进行有效的管理,状态在什么时候,由于什么原因,如何变化就会不受控制,就很难跟踪和测试了。


在软件开发里,有些通用的思想,比如隔离变化,约定优于配置等,隔离变化就是说做好抽象,把一些容易变化的地方找到共性,隔离出来,不要去影响其他的代码。约定优于配置就是很多东西我们不一定要写一大堆的配置,比如我们几个人约定,view 文件夹里只能放视图,不能放过滤器,过滤器必须放到 filter 文件夹里,那这就是一种约定,约定好之后,我们就不用写一大堆配置文件了,我们要找所有的视图,直接从 view 文件夹里找就行。


根据这些思想,对于状态管理的解决思路就是:把组件之间需要共享的状态抽取出来,遵循特定的约定,统一来管理,让状态的变化可以预测。


二.什么是Vuex



Vuex是一个专门为Vue.js应用程序开发做状态管理的.


他采用集中式存储管理应用的所有组件的状态, 并以响应的规则保证状态以一种可预测的方式发生变化.


1. 什么是状态管理呢?


vuex官网说到的"状态管理模式", "集中式存储管理", 这些词和"状态管理"都是一个含义. 就是管理状态.


我们通常会有很多组件, 组件之间可能会共享状态. 那么如何定义这个状态呢? 定义在某一个组件里面肯定是不合适的, 要定义在最外层.


用vue生态圈来说, 有多个组件要共享状态, 通常状态我们用变量来表示, 也就是多个组件之间共享变量. 当共享变量变多, 我们就是用一个对象来存储, 这个对象就是存储共享状态的对象. 通常, 这个对象放在vue顶层的实例中. 其他各个组件都可以使用.


而vue是响应式编程方式, 一个组件修改了状态, 其他组件能够实时响应么?这就是Vuex实现的功能.他的主要功能:


  1. 管理状态: 因为是将各种状态保存在一个地方, 所以也叫集中式存储管理 或者 集中式装填管理
  2. 响应式: 一个组件修改了状态, 其他组件能够实时响应


2. 通常什么状态需要放在Vuex中管理呢?


不是所有的状态都要交给vuex来管理的, 只有在多界面之间共享的状态, 我们才将其交给vuex来管理. 比如:


  • 用户登录状态: 用户名, 头像, 昵称等等. 很多页面可能都会用到用户的基本信息, 像这些统一的信息, 我们就可以放在统一的地方进行管理了.
  • token: 用户登录的令牌, 某些接口必须有令牌才能访问, 那么这些几口就需要共享token
  • 商品收藏, 购物车中的物品等. 我们在各个界面都可以添加商品搜藏, 都可以加购, 这时候, 就可以将其放入到vuex里面


放在vuex中, 不仅能够共享状态, 还能够实时响应.


3. Vuex的设计思想


Vuex 全局维护着一个对象,使用到了单例设计模式。在这个全局对象中,所有属性都是响应式的,任意属性进行了改变,都会造成使用到该属性的组件进行更新。并且只能通过 commit 的方式改变状态,实现了单向数据流模式。


Vuex集成到了Vue的官方调试工具devtools extension, 提供了诸如零配置time-travel调试,状态快照导入导出等高级调试功能.


三. Vuex是如何在多组件间进行状态管理的?



2.1. 单界面状态管理


之前我们遇到的都是在单界面进行状态管理. 单界面的状态管理有3个部分, 如下图所示:


00de5a31919e40e98e31396a9ac2365e_tplv-k3u1fbpfcp-zoom-1.png



第一部分: state

第二部分: view

第三部分: action


三部分是如何工作的呢? 通常状态我们会用一个变量来表示, 定义在组件的data属性中.


<script>
    export default {
        name: "calculate",
      data() {
          return {
            counter: 0
          };
      }
    }
</script>

然后,在页面中通过语法糖直接引用counter变量. counter的值就在页面中显示了.

最后, 我们还可以在页面中增加action, 比如点击事件, 来改变state的状态.


以上是在单页面中状态管理的流程.


2.2. 多界面状态管理


举个例子, 比如,我们有一个calculate.vue组件

data() {
          return {
            counter: 0
          };
      },
      methods: {
          add() {
            this.counter ++
          },
          dev() {
            this.counter --
          }
      }
    }
</script>

然后在App.vue中引入calculate.vue组件


<script>
import Calculate from './views/calculate'
export default {
  name: 'App',
  components: {
    Calculate,
  }
}
</script>

这时, 如果想要在App.vue中使用calculate.vue中定义的变量counter, 可以么?


直接使用肯定会报错, 但Calculate和App两个组件的关系是父子组件, 可以使用父子组件变量传递的方式实现.


如果不是父子关系呢? 需要如何实现呢?我们可以使用vuex.


2.3. Vuex的使用


使用vuex, 首先需要安装vuex组件


npm install vuex --save

--save表示的含义是: 运行时需要


组件安装好了, 下面就来看看怎么用吧.


第一步: 添加vuex代码文件夹


在src目录下新建/src/store/index.js. 通常, vuex都放在store文件夹里面. 然后在store下面创建一个文件index.js


第二步: 在index.js文件中定义vuex组件.


vuex是一个插件, vue-router也是一个插件, 插件的使用方式都是类似的.


1: 引入vue和vuex


import Vue from 'vue';
import Vuex from 'vuex';

2: 安装vuex


Vue.use(Vuex);

3: 创建vuex对象


const store = new Vuex.Store({
    state: {
    },
    mutations: {
    },
    actions: {
    },
    getters: {
    },
    modules: {
    }
})

在store中定义了5个对象, 这5个对象是固定的. 每个对象的含义是什么呢? 后面在详细说.

4: 导出vuex


export default store;

5: 在main.js中引入vuex


import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index';
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  render: h => h(App)
})

接下来在来看看2.2中多界面状态管理的问题. calculate组件中有一个counter, 在父组件App.vue中想要使用counter, 这时候, 这个counter就是一个公共的状态了, 可以将其定义在vuex中.


2.4 Vuex实现多界面状态管理


下面来看看使用vuex的方式如何实现呢?


1. 在vuex的state中定义一个变量counter


// 第三步: 创建vuex对象
const store = new Vuex.Store({
  state: {
    counter:0
  }
})

2. 在calculate.vue中使用$store.state.counter来获取vuex中counter变量


<template>
  <div>
    <h2>{{$store.state.counter}}</h2>
  </div>
</template>

这样就显示出来了counter变量了. 并且, 可以在calculate.vue或者App.vue, 或者任何其他组件中都可以直接使用. 如下图所示:


a6dd05d0b9db4063aae956d1a92ae560_tplv-k3u1fbpfcp-zoom-1.png

接下来要实现+和-的操作.


这个怎么实现呢? 我们可能会这么想

<template>
  <div>
    <h2>-------calculate.vue-------</h2>
    <h2>{{$store.state.counter}}</h2>
    <button v-on:click="$store.state.counter++">+</button>
    <button v-on:click="$store.state.counter--">-</button>
  </div>
</template>

$store.state.counter++或者$store.state.counter--不就可以了么?


虽然, 这样也能达到效果, 但是Vuex官网推荐我们不要这样使用, 原因是, 这样操作完, 我们不能跟踪到状态的变化. 这是什么意思呢, 这就要来看看vuex的设计思想了.


2.5 Vuex式的设计思想


Vuex实质是单例模式的设计思想


  • 将共享的状态抽取出来, 交给大管家, 进行统一管理
  • 之后, 每一个视图, 按照规定好的规则, 执行访问或修改等操作.
  • 这就是vuex背后的思想.


这里规定好的规则很重要. 规定好的规则是什么规则呢? 我们来看一下vuex官方给出的一个图

22a45891b0274cd19bf7a948222e269f_tplv-k3u1fbpfcp-zoom-1.png

这里面一共有5个元素


  • Vue compontents
  • State
  • Mutations
  • Action
  • Devtools

    这几个部分都是做什么用的呢?


1. Vue Components


在这个图里面绿色的部分是Vue compontents(Vue组件), Vue组件可以引用state变量, 还可以触发操作修改变量的值.


2. State:


State用来存储的是变量, 变量值可以直接渲染到Vue组件上, 但是约定好的, Vue组件不可直接修改State的值


3. Mutations 和 Devtools


如果Vue组件想要修改state中的状态, 他不能直接修改State, 而是需要执行commit, 提交到Mutations, 由Mutations触发修改state的状态. 为什么要这样呢? 这就和Devtools有关系了.


我们看到有一块灰色的Devtools, 这是什么呢? 这是Vue开发的一款浏览器插件. 这个插件可以帮助我们记录每次state中变量修改的状态, 为什么要记录state的状态呢?

比如, 我们有多个组件同时修改vuex中的一个状态, 那么大家都来改, 最终这个值是谁改的呢? 如果没有记录状态变化, 那么我们就不知道是谁改的了. Vue提供的Devtools工具, 就可以用来记录每次修改的状态.


但是, 如果我们直接修改组件, 那就没有经过Devtools的流程, Devtools也就记录不了了. 也就是直接从state修改变量值(红色箭头), 而不是走蓝色箭头的流程, 那么没有经过Devtools, Devtools也不能记录上修改的状态了.


6ee7227468634c1a9922a041ca4b4c0c_tplv-k3u1fbpfcp-zoom-1.png

4. Action


Action主要是用来进行异步处理操作的. mutations是用来处理同步操作的, 所以, vue组件想要修改变量的时候, 直接走mutations就可以了, 这样也可以通过Devtools来记录修改情况. 但是, 如果异步怎么办呢? devtools只能用来记录同步状态, 如果出现异步, 他就记录不了了. 所以, 这里多了一个action. action就是用来处理异步操作的. 当action处理完了以后, 再交给Mutations来处理, 这时候就是同步的操作了, Devtools也可以处理了.

什么情况会进行异步操作呢?


发送网络请求. 所以在Action模块指向了BackEnd, 向后端发送网络请求.


2.6 Devtools的使用


1. 安装Devtools


下面我们就来安装Devtools

打开google浏览器, 点击右上角三个点-->更多工具-->扩展程序-->打开Chrome网上应用店-->搜索Devtools, 如下图:

f6df05a09c0a4174a772ffcd8de46304_tplv-k3u1fbpfcp-zoom-1.png

找到VueJs的Devtools-->添加至Chrome, 如下图:


b2804eb8cb3b43858230fef5bacdde30_tplv-k3u1fbpfcp-zoom-1.png


然后安装插件即可.


2. 使用Devtools跟踪状态


Chrome安装好Devtools以后,打开控制台, 在菜单栏最后多了一个vue, 点开可以看到如下界面:

37ec0114961846a5b8f75fa6e9b4682b_tplv-k3u1fbpfcp-zoom-1.png


其中,第二个按钮是监控变量状态变化的.

4e71ea0826564305bd9cd1f8f00fd999_tplv-k3u1fbpfcp-zoom-1.png


我们如果直接使用$store.state.counter++, 在Devtools是无法监控状态变化的,但是如果我们使用mutations就可以监控到状态变化.

3.在mutation中修改counter的值

首先, 我们是要在页面实现+和-的逻辑, 如下图:

dc9784b48ebf4ba7a8311efa60c2e189_tplv-k3u1fbpfcp-zoom-1.png


这个逻辑在calculate.vue组件会用到, 在App.vue组件也会用到, 因此我们将其定义在vuex插件中. 在插件里面定义两个方法:increase()和decrease(), 修改变量counter的值


const store = new Vuex.Store({
  state: {
    counter: 100
  },
  mutations: {
    increase(state) {
      state.counter ++;
    },
    decrease(state) {
      state.counter --;
    }
  }
})

这两个方法increase()和decrease(), 他们自带的参数就是state.


在调用方如何定义呢? 也就是calculate.vue和App.vue中应该如何使用Vuex中定义的两个mutations方法呢?


<template>
  <div>
    <h2>-------calculate.vue-------</h2>
    <h2>{{$store.state.counter}}</h2>
    <button v-on:click="add()">+</button>
    <button v-on:click="sub()">-</button>
  </div>
</template>
<script>
    export default {
        name: "calculate",
      data() {
          return {
          };
      },
      methods: {
        add() {
          this.$store.commit("increase");
        },
        sub() {
          this.$store.commit("decrease")
        }
      }
    }
</script>


在调用方, 我们要使用this.$store.commit()的方式来提交变更.

image.png

在左侧点击+或-,在右侧devtools都会记录每一次状态变化.


2.7 总结


Vuex 应用的核心就是 store(仓库), “store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:


  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。



相关文章
|
2月前
|
资源调度 JavaScript API
从入门到精通:Vuex使用教程,让你更好地管理应用程序状态!
Vuex是Vue.js的一个状态管理库,它可以帮助我们更好地管理应用程序的状态。在Vue.js中,组件之间的通信往往需要借助于props和emit来完成,但是当应用程序的状态变得比较复杂时,这种方式就变得比较麻烦。Vuex可以帮助我们更好地管理状态,以及在组件之间共享状态。
|
3月前
|
小程序
uniapp项目实践第一章:如何创建uniapp项目
uniapp项目实践第一章:如何创建uniapp项目
29 1
|
3月前
|
小程序 开发工具 git
uniapp项目实践第三章:初始化项目
uniapp项目实践第三章:初始化项目
25 0
|
5月前
|
存储 JavaScript 前端开发
Vuex的简介以及入门案例
Vuex的简介以及入门案例
|
5月前
|
Web App开发 小程序 机器人
uniapp案例30余种实战项目
uniapp案例30余种实战项目
|
JavaScript 数据安全/隐私保护
【Vue 开发实战】实战篇 # 39:创建一个分步表单
【Vue 开发实战】实战篇 # 39:创建一个分步表单
177 0
【Vue 开发实战】实战篇 # 39:创建一个分步表单
|
8月前
|
JavaScript 前端开发 中间件
【vue入门手册】七、案例开发-表格增删改查
【vue入门手册】、案例开发-表格增删改查
174 0
|
9月前
|
资源调度 JavaScript 前端开发
Vue3框架的创建的两种种方案(第十二课)
Vue3框架的创建的两种种方案(第十二课)
45 0
|
9月前
|
JavaScript 开发者
elementui是什么,简要概述?
elementui是什么,简要概述?
440 0
|
10月前
|
JavaScript 编译器 API
Vue项目实战——实现GitHub搜索案例(学以致用,两小时带你巩固和强化Vue知识点)
Vue项目实战——实现GitHub搜索案例(学以致用,两小时带你巩固和强化Vue知识点)