概述及使用场景

Vuex 是一个主要应用在中大型单页应用的类似于 Flux 的数据管理架构。它主要帮我们更好地组织代码,以及把应用内的的状态保持在可维护、可理解的状态。

但如果是简单的应用 ,就没有必要使用vuex来管理状态了, 只会增加应用的复杂性 ,一个简单的应用完全可以使用$emit这种方式就可以来解决https://cn.vuejs.org/v2/guide/components.html#非父子组件的通信。 比如 ,通过父组件传值给子组件,子组件处理完数据,

如果需要对该属性值进行变更,则再发送给父组件就可以了,不需要使用vuex,

但是如果是大型项目中的公共属性,多个不关联的组件之间都需要使用某个属性,

如果这时候再使用传值就特别的不方便,逻辑很混乱,这时候放到vuex仓库就很简单了,

某组件对vuex的属性更改完了,其他任何组件都可以拿来用

用一张图来理解

以上是官方提供的一张状态管理图,从图中可以看出以下几点:

1、整个过程它是一个单向的数据流

2、涉及到几个核心概念Actions,mutations和state

3、组件可以调用actions,通过action来分发mutations ,只有 mutations 可以修改状态,store(仓库) 是响应式的,即状态的变化会在组件内部得到反映

另外,每一个 Vuex 应用的核心就是 store(仓库),包含着你的应用中大部分的状态 (state),他和单纯的全局对象不同的是:

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

2、不能直接改变 store 中的状态,改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation

vuex核心概念

state单一状态树

组件中获取状态,在计算属性中返回某个状态,例如

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

当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM

以上模式组件依赖全局状态单例,需要在每个使用 state 的组件中需要频繁地导入,vuex提供了一种机制将状态从根组件“注入”到每一个子组件中,通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,在子组件中就可以通过this.$store形式访问到

const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余,这时候可以使用 mapState辅助函数帮助我们生成计算属性

1、通过import先把mapState 导入进来
import { mapState } from 'vuex'
2、使用mapState
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})

当计算属性的名称与 state 的子节点名称相同时,也可以给 mapState 传一个字符串数组

computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])

通过对象展开运算符可以使用...mapState形式简化写法

computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}

getters,从 store 中的 state 中派生出一些状态

有时候我们需要从 store 中的 state 中派生出一些状态,例如过滤某个数组,可以在组件中的计算属性中获取到state然后过滤,但如果我们要在多个组件中去使用它,这样做法不太理想,这时我们可以在store中定义一个getters

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

组件中使用getters

computed: {
doneTodosCount () {
return this.$store.getters.doneTodos
}
}

使用mapGetters 辅助函数将 store 中的 getter 映射到局部计算属性

import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}

mutation提交,更改store状态

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),Vuex 中的 mutation 非常类似于事件

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

如果要调用increment函数时,要唤醒一个 mutation handler,需要以相应的 type 调用 store.commit 方法

store.commit('increment')
也可以向 store.commit 传入额外的参数
mutations: {
increment (state, n) {
state.count += n
}
} store.commit('increment', 10)
这里的参数也可以是一个对象
store.commit('increment', {
amount: 10
})

使用常量替代 mutation 事件类型,这在多人协作的大型项目中,很有帮助,当然也可以不使用,看情况。

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION' // store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({
state: { ... },
mutations: {
// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
[SOME_MUTATION] (state) {
// mutate state
}
}
})

在组件中使用 this.$store.commit('xxx') 提交 mutation,也可以使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)

import { mapMutations } from 'vuex'

export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')` // `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}

使用Action可以使得在mutation中更方便的使用异步

在 Vuex 中,mutation 都是同步事务,Action 类似于 mutation,但不同的是Action 提交的是 mutation,而不是直接变更状态,并且可以包含任意异步操作

1、注册action

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

在我们需要调用 commit 很多次的时候,使用ES2015 的 参数解构 来简化代码

actions: {
increment ({ commit }) {
commit('increment')
}
}

2、分发action

Action 通过 store.dispatch 方法触发:

store.dispatch('increment')

看上去有点多此一举,为何不直接分发mutation,这是因为 mutation 必须同步执行,而我们可以在 action 内部执行异步操作

actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}

同样,也可以使用载荷方式和对象方式进行分发

// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
}) // 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})

3、在组件中分发action

在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用

import { mapActions } from 'vuex'

export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` // `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}

module,将 store 分割成模块

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(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 的状态

vuex调试工具

https://github.com/vuejs/vue-devtools

相关文章

用 Vuex 构建一个笔记应用

https://segmentfault.com/a/1190000005015164

从一个改写后的vue小应用认识vuex

https://www.jianshu.com/p/9dcbe1fec24d

作者:fozero

声明:原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/8094265.html

标签:vuejs,vuex,前端

vuex状态管理之学习笔记的更多相关文章

  1. 前端MVC Vue2学习总结(八)——Vue Router路由、Vuex状态管理、Element-UI

    一.Vue Router路由 二.Vuex状态管理 三.Element-UI Element-UI是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架,手机端有对应框架是 Mint U ...

  2. 前端Vue框架-vuex状态管理详解

    新人报道!多多关照-多提宝贵意见 谢谢- vuex理解 采用集中式存储管理模式.用来管理组件的状态,并以自定义规则去观测实时监听值得变化. 状态模式管理理解 属性 理解 state 驱动应用的数据源 ...

  3. vuex状态管理-数据改变不刷新

    困惑: 在页面初始化的时候,我提交到vuex状态管理,然后在获取的时候获取不到,我找到了出错的地点,并进行了修改,然后可以获取到状态 但是不知道原因? 定义了如下的state const state ...

  4. vuex状态管理demo

    vuex状态管理主要包含四个概念  mapState,mapMutations,mapGetters,mapActions. 编写vuex文件夹下面的store.js import Vue from ...

  5. 前端技术之:如何在vuex状态管理action异步调用结束后执行UI中的方法

    一.问题的起源 最近在做vue.js项目时,遇到了vuex状态管理action与vue.js方法互相通信.互操作的问题.场景如下图所示: 二.第一种解决方法 例如,我们在页面初始化的时候,需要从服务端 ...

  6. VueX状态管理器 的应用

    VueX状态管理器 cnpm i vuex axios -S 1 创建Vuex 仓库 import Vue from 'vue' import Vuex from 'vuex' vue.use(Vue ...

  7. vue第十八单元(单向数据流 vuex状态管理)

    第十八单元(单向数据流 vuex状态管理) #课程目标 1.理解什么是数据管理模式 2.什么是vuex 3.什么时候使用vuex 4.vuex安装及工作原理 5.vuex语法 #知识点 1.首先来看下 ...

  8. Vuex 状态管理的工作原理

    Vuex 状态管理的工作原理 为什么要使用 Vuex 当我们使用 Vue.js 来开发一个单页应用时,经常会遇到一些组件间共享的数据或状态,或是需要通过 props 深层传递的一些数据.在应用规模较小 ...

  9. vue 通信:父子通信、兄弟通信、跨多层通信、vuex状态管理

    之前简单做了一次vue通信方法的培训,在此记录一下培训的内容. 关于vue通信,大家最先想到的方法应该是props.ref.$emit.$parent,还有vuex,因为这也是我在项目中最常用到的方法 ...

随机推荐

  1. linux命令大全(1)

    当用户使用linux系统时,其实在和Shell在打交道,当用户发出指令,其实先将这些指令发送给Shell, 然后由Shell将用户的指令翻译后传送给内核,再由内核来控制硬件的工作. 然后内核将硬件的工 ...

  2. linux 查看信息-进程&用户&服务&程序

    进程 1.查看所有进程 2.实时显示进程状态 用户 1.查看活动用户 2.查看登录日志 3.查看系统所有用户 4.查看系统所有组 5.查看当前用户的计划任务 服务 1.列出所有系统服务 2.列出所有启 ...

  3. Vue入门---常用指令详解

    Vue入门 Vue是一个MVVM(Model / View / ViewModel)的前端框架,相对于Angular来说简单.易学上手快,近两年也也别流行,发展速度较快,已经超越Angular了.比较 ...

  4. Beta冲刺 (4/7)

    Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 共享编辑文章的后端数据处理 展示Gi ...

  5. Docker环境安装与配置

    Docker 简介 Docker使用Go语言编写的 安装Docker推荐LInux内核在3.10上 在2.6内核下运行较卡(CentOS 7.X以上内核是3.10) Docker 安装 安装yum-u ...

  6. hdu 1069 Monkey and Banana 【动态规划】

    题目 题意:研究人员要测试猴子的IQ,将香蕉挂到一定高度,给猴子一些不同大小的箱子,箱子数量不限,让猩猩通过叠长方体来够到香蕉. 现在给你N种长方体, 要求:位于上面的长方体的长和宽  要小于  下面 ...

  7. python 使用 sorted 对 列表嵌套元组的数据进行排序

    在开发的过程可能会遇到这么一个需求,存在一个列表嵌套元组的数据: data = [(1, 'a'),(2, 'b'),(5, 'c'),(3, 'd'),(4, 'e')] 需要将这个列表按照元组的第 ...

  8. ES6教程-字符串,函数的参数,了解函数的arguments对象,js面向对象,设计模式-单例模式,解构赋值

    前言 主要讲解了ES6对字符串的拓展,包括includes,startsWith和endsWith,另外增加了字符串模板. Start includes()是否包含 startsWith()以什么开头 ...

  9. EXCEL在改动某几个单元格时隐藏空列

    概述 今天我哥来找我帮他搞下excel表格,本着程序猿对程序无所不能的精神,我爽快的答应了.结果查了半天才搞定.现在记录在此,供自己以后参考,相信对其他人也有用. PS:这几天正在弄博客,马上就要弄完 ...

  10. 谈谈我们对userAgent的看法,为什么爬虫中需要userAgent?

    首先打开浏览器,按 F12 进入控制台(Console),然后输入:navigator.userAgent,即可看到 UA.例如: 1 2 Mozilla/5.0 (Windows NT 10.0; ...