您的位置:首页 > Web前端 > Vue.js

从零开始的vue学习笔记(七)

2019-10-15 22:24 831 查看

前言

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

Vuex是什么

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

它包含三个部分:

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

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

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

实际上就是一个组件间通讯的问题,原来是用$ref直接引用子组件,或者多层嵌套组件,或者依赖注入

provide
inject
等暴力方式,在应用和组件复杂的情况下复杂度和可维护性都会成为巨大问题。

所以,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
    这一长串,其他的辅助函数
    mapGetters
    mapActions
    mapMutations
    都是类似的作用,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
    确保每个模块的独立命名空间,更多语法细节见链接

  • 其他
    其他的主题包括:
      项目结构
    • 插件
    • 严格模式
    • 表单处理
    • 测试
    • 热重载

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

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: