前言

今天花一天时间阅读完vuex的官方文档,简单的做一下总结和记录

Vuex是什么

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,以前的符合“单向数据流”理念的示意图:

它包含三个部分:

  • state,驱动应用的数据源;
  • view,以声明方式将 state 映射到视图;
  • actions,响应在 view 上的用户输入导致的状态变化。

当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

  • 多个视图依赖于同一状态。
  • 来自不同视图的行为需要变更同一状态。

实际上就是一个组件间通讯的问题,原来是用$ref直接引用子组件,或者多层嵌套组件,或者依赖注入provideinject等暴力方式,在应用和组件复杂的情况下复杂度和可维护性都会成为巨大问题。

所以,vuex就诞生了,vuex的原理图:

这个图描述了vuex的数据传导逻辑,绿色虚线部分为vuex插件本身

  1. 首先,Vuex自身提供了一个store(仓库),数据结构为树形的,采用单例设计,里面用key-value(value可以是string、数字、数组、Object等)的形式包含了一个应用的各种状态值,并提供了响应式的状态更新,提供给vue组件Render来渲染。
  2. 传统的Vue组件接受用户对界面的操作后,通过分发(Dispatch)这些前端事件或者说响应给Vuex的Action,在Action中可以用来添加自己的业务逻辑,同时可以异步调用一些其他的后端API
  3. Action通过Commit来提交对应的Mutations里的方法,达到调用Mutations里的方法的目的,这个时候可以用Devtools插件来追踪状态数据在Mutations里的方法调用前后的数据变化,形成快照等(Mutations里的方法必须同步的)
  4. Mutations里的一些mutation(变异)方法体执行,改变应用的一些State状态属性,这些mutation是Vuex改变状态的唯一途径,直接修改State状态值是不允许的(数据不可追踪),从而形成了单向数据流的完整链路,同时状态是可维护可追踪响应式可复用

下面就一起来看看Vuex的各个详细部分:

安装

  • 直接下载(推荐)或者CDN引入

    从https://unpkg.com/vuex下载下来,然后通过js引入:

      <script src="/path/to/vue.js"></script>
    <script src="/path/to/vuex.js"></script>
  • npm/yarn

      //npm
    npm install vuex --save
    //yarn
    yarn add vuex
  • 模块化的打包系统

    import Vue from 'vue'
    import Vuex from 'vuex'
    //前面vue基础部分就有Vue.use()引入插件的用法,
    //下面这句在打包系统中是必备的
    Vue.use(Vuex)

核心概念

  • State

    首先,Vuex的所有概念都只有一个api:围绕Vuex.Store(...options) 这个构造器展开,类似Vue的概念都围绕Vue的构造器展开一样;State的作用就类似于Vue里面的data,简单的new Vuex的例子:
      // 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex)
    
      const store = new Vuex.Store({
    state: {
    count: 0
    },
    mutations: {
    increment (state) {
    state.count++
    }
    }
    })

    这样,在我们的Vue插件里就可以用computed计算属性来获取这些state值:

      // 创建一个 Counter 组件
    const Counter = {
    template: `<div>{{ count }}</div>`,
    computed: {
    count () {
    return store.state.count
    }
    }
    }

为了简化写法(少些代码),官方提供了一个mapState辅助函数避免写store.state.count这一长串,其他的辅助函数mapGettersmapActionsmapMutations都是类似的作用,API链接

例子:

  // 在单独构建的版本中辅助函数为 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
}
})
}
  • Getter

    单纯的用State里的状态值还不够强大,所以Vuex提供了Getter来对State作进一步的复杂逻辑处理,类似于Vue里面的computed计算属性对data的进一步处理一样。

    例子:
      const store = new Vuex.Store({
    state: {
    todos: [
    { id: 1, text: '...', done: true },
    { id: 2, text: '...', done: false }
    ]
    },
    getters: {
    doneTodos: state => {
    return state.todos.filter(todo => todo.done)
    }
    }
    })

如果对更多的语法细节感兴趣,可以阅读官方链接

  • Mutation

    Mutaion中文解释是变异,用来执行对State状态改变的同步方法,可以简单的类比Vue中的methods,只不过Vue中的methods没有区分同步异步方法,而Vuex中为了追踪数据状态,用Mutation执行同步方法,Action直观性异步方法,做了这种拆分,让Devtools等工具发挥作用。

    例子:

      const store = new Vuex.Store({
    state: {
    count: 1
    },
    mutations: {
    increment (state) {
    // 变更状态
    state.count++
    }
    }
    })

    更多的语法细节参考链接

  • Action

    Action 类似于 mutation,不同在于:

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

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

    组件里通过store.dispatch 来出发actions

      store.dispatch('increment')

    更多语法细节见链接

  • Module

    如果只靠一个大的store里的state状态树来维护整个应用,当规模巨大,势必会有问题,所以引入Module做模块化的拆分,拆成按照命名空间的子状态树。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

    例子:

      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 的状态

    引入namespaced: true 确保每个模块的独立命名空间,更多语法细节见链接

  • 其他

    其他的主题包括:

    • 项目结构
    • 插件
    • 严格模式
    • 表单处理
    • 测试
    • 热重载

这些主题不是核心问题,在需要看的时候或者自己感兴趣的再来看,详见链接

从零开始的vue学习笔记(七)的更多相关文章

  1. 从零开始的vue学习笔记(一)

    前言 项目要用vue.js,今天开始自学vue.js官方教程,记录下自己的学习摘要,方便后面查阅(此笔记按照学习天数,每天一篇) Vue.js是什么 Vue是一套用于构建用户界面的渐进式框架,Vue ...

  2. 从零开始的vue学习笔记(八)

    前言 今天花一天时间阅读完Vue Router的官方文档的基础部分,简单的做一下总结和记录 Vue Router是什么 Vue Router 是 Vue.js 官方的路由管理器,用于构建单页应用(SP ...

  3. vue学习笔记(七)组件

    前言 在前面vue的一些博客中,我们几乎将vue的基础差不多学习完了,而从本篇博客开始将会进入到vue的另一个阶段性学习,本篇博客的内容在以后的vue项目中占很大的比重,所以小伙伴们需要认真学习,本篇 ...

  4. 从零开始的vue学习笔记(五)

    单文件组件 Vue.component 来定义全局组件的缺点: 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复 字符串模板 (String te ...

  5. Vue学习笔记七:Vue中的样式

    目录 两种样式 class样式 内联样式 两种样式 Vue中使用样式方式有两种,一种是class样式,一种是内联样式也就是style class样式 class样式使用的方式有5种,HTML如下 &l ...

  6. 从零开始的vue学习笔记(二)

    数据与方法 当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中.data的数据和视图同步更新. 实例创建后添加一个新的属性,对这个属性的的改动将不会触发任何 ...

  7. 从零开始的vue学习笔记(四)

    组件注册 组件名 Vue.component('my-component-name', { /* ... */ }) 这里的my-component-name就是组件名,组件名的取法可以参考指南 ke ...

  8. 从零开始的vue学习笔记(六)

    混入 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能.简单解释就是把一个Vue组件中的内容提供给别的组件来用.例子: // 定义一个混入对象 var myMixin ...

  9. 从零开始的vue学习笔记(三)

    事件处理 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码,示例: <div id="example-2"> <!-- `gree ...

随机推荐

  1. 为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?

    面试题 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka.ActiveMQ.RabbitMQ.RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: ...

  2. EF Core 通过延迟加载获取导航属性数据

    EF 6及以前的版本是默认支持延迟加载(Lazy Loading)的,早期的EF Core中并不支持,必须使用Include方法来支持导航属性的数据加载. 当然在EF Core 2.1及之后版本中已经 ...

  3. 【Offer】[44] 【数字序列中某一位的数字】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 数字以0123456789101112131415..的格式序列化到一个字符序列中.在这个序列中,第5位(从0开始计数)是5,第13位是 ...

  4. 封装axios来管控api的2种方式

    前言:我们在开发项目的时候,往往要处理大量的接口.并且在测试环境 开发环境 生产环境使用的接口baseurl都不一样 这时候如果在开发环境完成之后切换每一个接口的baseurl会变的非常的麻烦,(要去 ...

  5. 换个角度使用VUE过滤器

    换个角度使用VUE过滤器 过滤器在Vue中的主要用于文本格式化,如小写转大小,日期格式化等操作.官方对这个功能介绍也很简单,不过确实很简单,就一个函数而已.但最近在做两款APP时,遇到一些特殊的需求. ...

  6. cmd命令查看已连接的WiFi密码

      实验环境:Windows 10.命令提示符(管理员权限) 一.CMD命令查看WiFi密码 使用方法: ①.运行CMD(命令提示符) (确保无线网卡启用状态)②.输入命令查看WiFi配置文件:  # ...

  7. Java的初始化块及执行过程详解

    问题:Java对象初始化方式主要有哪几种?分别是什么?针对上面的问题,想必大家脑海中首先浮现出的答案是构造器,没错,构造器是Java中常用的对象初始化方式. 还有一种与构造器作用非常相似的是初始化块, ...

  8. 删除mac开机启动项

    1、开“系统偏好设置”窗口,选择“用户与群组”,进入用户与群组窗口.选择登录项选项卡,再解锁,最后删除开机启动的应用.   2、分别在以下6个目录中检查是否有与anydesk相关的plist文件 ~/ ...

  9. 小白专场-FileTransfer-c语言实现

    目录 一.集合的简化表示 二.题意理解 三.程序框架搭建 3.1 Input_connection 3.2 Check_connection 3.3 Check_network 四.pta测试 五.按 ...

  10. JAVA设计模式-动态代理(Proxy)源码分析

    在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...