Vuex基本概念
Vuex基本概念
State
Getter
Mutation
Action
Module
简单的Store
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(vuex);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++;
}
}
});
store.commit('increment');
console.log(store.state.count);// 1
常见流程
Vue Component
--dispatch--> Action
Action
--commit--> Mutations
Mutations
--mutate--> State
State
--render--> Vue Component
State
获取vuex中的状态方法
在计算属性:computed
中返回某个状态,要获取Vuex那个状态,要在computed
中定义
由于在全局使用了Vue.use(Vuex)
,所有组件可以通过this.$store
拿到Vuex的store
const Counter = {
template: `<div>{{count}}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
由于computed的属性是函数
,那么在返回状态之前,还有更多操作的空间。
mapState辅助函数
import {mapState} from 'vuex'
mapState
辅助函数接收一个对象
或者一个字符串数组
,返回计算属性:computed
//这个可以单独放在一个文件中,重复使用
const vuexComputed = mapState({
//使用函数一定要有返回值
//箭头函数写法,第一参数是state
count: state => state.count,
//字符串形式 'count' 等同于 state => state.count
countAlias: 'count',
//可以使用'this'获取局部状态,使用常规函数,'this'会绑定为 computed的组件实例
countPlusLocalState (state) {
return state.count + this.localCount;
}
});
然后将mapState生成的vuexComputed和Vue组件实例的computed合并
使用对象展开运算符...
{
//...某个组件
computed: {
localComputed () {},
//使用对象展开运算符将vuexComputed混入到外部对象中
...vuexComputed
}
}
如果状态都只是单纯的显示,可以传一个字符串数组
给mapState
const vuexComputed = mapState(['count']);
完整的demo:
//main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
store.commit('increment')
console.log(store.state.count)
Vue.config.productionTip = false
Vue.prototype.$http = axios
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
components: { App },
template: '<App/>'
})
main.js
要使用Vue.use(Vuex)
以及将store
添加到全局new Vue({store})
下面的所有子组件
才可以拿到store
<template>
<div class="hello">
<div>{{count}}</div>
<div>{{countAlias}}</div>
<div>{{countPlusLocalState}}</div>
</div>
</template>
//Component HelloWorld
import {mapState} from 'vuex'
const vuexComputed = mapState({
count: state => state.count,
countAlias: 'count',
countPlusLocalState (state) {
return state.count + this.localCount
}
})
export default {
name: 'HelloWorld',
data () {
return {
localCount: 2
}
},
computed: {
...vuexComputed
}
}
Getter
Getter
和计算属性:computed
功能一样,只不过,它是store
的,也会缓存计算的值。
组件中拿到getter
Getter
会暴露store.getters
对象。
const store = new Vuex.Store({
state: {
count: 0,
arr: [1, 2, 3, 4, 5, 6]
},
mutations: {
increment (state) {
state.count++
}
},
getters: {
get6: state => {
return state.arr.filter(num => num === 6)
}
}
})
{
//...某个组件
computed: {
get6 () {
return this.$store.getters.get6
}
}
}
在定义getter
时,有两个参数传入state
、getters
getters: {
get6: state => state.arr.filter(num => num === 6),
getNum: (state, getters) => {
return getters.get6
}
}
定义getter方法
//要使用函数要封装2层函数以上,在组件中拿到getTodoById时,默认执行第一层
getters: {
getTodoById: state => id => state.todos.find(todo => todo.id === id)
}
store.getters.getTodoById(2)
mapGetters
功能:将store
中的getter
映射到局部的计算属性computed
中
和mapState
类似,支持传入对象
或者字符串数组
,不过只能获取,不能重写,或者定义
//store
{
state: {
arr: [1, 2, 3, 4, 5, 6, 7, 8]
},
getters: {
get6: state => {
return state.arr.find(num => num === 6)
},
getNum: state => num => state.arr.find(n => n === num) || '错误num'
}
}
<template>
<div class='helloworld'>
<div>{{get6}}</div>
<div>{{getNum(4)}}</div>
</div>
</template>
const vuexGetter = mapGetters(['get6', 'getNum']);
//如果想定义别名使用对象的方式
//const vuexGetter = mapGetters({getSix: 'get6', getNumber: 'getNum'})
export default {
name: 'HelloWorld',
data () {
},
computed: {
...vuexGetter
}
}
Mutation
修改Vuex
的store
中的状态的唯一方式是commit mutation
。
每个mutation
都有一个字符串的事件类型(type)和一个回调函数(handler)
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
//type: increment
store.commit('increment')
Payload
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
store.commit
可以支持多参数模式
,或者一个对象模式
store.commit({
type: 'increment',
amount: 10
})
其中一个对象模式
和redux
很像
而且事件类型type也可以使用常量来替代
// 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
}
}
})
组件中提交mutation
在组件中可以通过this.$store.commit('xxx')
提交mutation
还有就是使用mapMutations
辅助函数,不过这次不是映射到计算属性,而是methods
使用方式和mapGetters
一模一样
import { mapMutations } from 'vuex';
//对象的方式可以重新命名,字符串数组是直接引用
const vuexMutations = mapMutations(['increment']);
export default {
methods: {
...vuexMutations
}
}
Mutation 和 Reduce
Reduce
的基本形式
(state, Action) => newState || state
转化为Mutation
,那么
const Action = {
type: 'increment',
amount: 10
}
const initState = {
count: 0
}
export default (state = initState, Action) => {
switch(Action.type){
'increment':
return Object.assign({},state,{count: Action.amount + state.count})
default:
return state
}
}
在redux
中改变状态:
store.dispatch(Action) -> reduce(state, Action) -> newState -> render view
在mutation
中改变状态:
store.commit('increment', playload) -> mutations['increment'](state, playload) -> newState -> render view
Action
一般Action
可以处理异步任务,而Mutation
必须只能同步。
在异步流程中,先异步获得所需的数据,然后将返回的数据组合成Action
。
在生成Action
之前,有个createAction函数
。
//Redux 思维的Action
const createAction = async (url) => {
const resData = await asyncGetData(url)
return {
type: 'SOME_TYPE',
resData
};
};
//Action 是对象
const Action = createAction('some url')
store.commit(Action)
在Vuex
中的Action
和Redux
是有区别的
在Vuex
中的Action
充当着createAction
的功能
commit
应当只在action
中使用,在commit
之前还有dispatch
在Redux
中,dispatch
分发的直接是action
在Vuex
中,dispatch
分发的是createAction或者mutation
,之后再commit action
Action 不同于 Mutation
- Action提交的是mutation,而不是直接变更状态
- Action可以包含任意异步操作
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action函数接受一个与store实例
具有相同方法和属性的context对象
其中context
不是store实例
分发Action
store.dispatch('increment')
组件中分发Action
组件中使用this.$store.dispatch('xxx')
或者使用mapActions
辅助函数将actions
映射到methods
中
组合Action
dispatch
函数在结束后返回一个Promise
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
Module
可以将store
分割成模块Module
每个模块拥有自己的State、Mutation、Action、Getter
然后将所有模块组合成一个,就形成了一个状态树。
//一般我们可以按页面或者功能模块来划分模块
//大型项目可以按一个大模块划分
//然后在大漠块中再按页面划分
//如果还要更细,页面也可以切割成多个模块
//页面A的状态
const pageA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
//页面B的状态
const pageAB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: pageA,
b: pageAB
}
})
store.state.a // -> pageA 的状态
store.state.b // -> pageAB 的状态
模块的局部状态
每个模块的state
都是局部状态,模块中的getter
、mutation
、传进来的state
都是局部的
而action
可以通过context.state
拿到局部的状态,context.rootState
拿到全局的
不同于mutation
,getter
也可以拿到全局状态,getter的第三个参数rootState
命名空间
默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的--多个模块对同一mutation或action作出响应
多个模块对同一mutation或action作出响应
,类似一个事件拥有多个处理程序(观察者模式)
在模块中添加namespace: true
可以避免添加到全局队列中
添加命名空间后的getter : (state, getters, rootState, rootGetters) => {}
添加命名空间后的action context : getters访问局部的 rootGetters访问全局的
如果添加了命名空间,但是还是想暴露某个action
或getter
为全局,使用root:true
{
actions: {
someOtherAction ({dispatch}) {
dispatch('someAction')
}
},
modules: {
foo: {
namespaced: true,
actions: {
someAction: {
root: true,
handler (namespacedContext, payload) { ... } // -> 'someAction'
}
}
}
}
}
mapState
、mapGetters
、mapActions
、mapMutations
绑定带命名空间的模块。
computed: {
...mapState('some/nested/module', {
a: state => state.a,
b: state => state.b
})
},
methods: {
...mapActions('some/nested/module', [
'foo',
'bar'
])
}
还可以使用createNamespacedHelpers
来绑定命名空间值,类似bind(context)
import { createNamespacedHelpers } from 'vuex';
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module');
export default {
computed: {
// 在 `some/nested/module` 中查找
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// 在 `some/nested/module` 中查找
...mapActions([
'foo',
'bar'
])
}
}
模块动态注册
// 注册模块 `myModule`
store.registerModule('myModule', {
// ...
})
// 注册嵌套模块 `nested/myModule`
store.registerModule(['nested', 'myModule'], {
// ...
})
//卸载'myModule',只能卸载动态装载的模块
store.unregisterModule('myModule')
应用
如果是小型应用,可以按页面来分模块
//pagea.js
export default {
namespace:true,
state: {},
getters: {},
mutations: {},
actions: {}
}
//pageb.js
//pagec.js
//paged.js
//以上页面也是按pagea.js的方式
然后用一个文件引进所有模块,且全部暴露export
//modules.js
import pageA from './pagea.js'
import pageB from './pageb.js'
import pageC from './pagec.js'
import pageD from './paged.js'
export default {
pageA,
pageB,
pageC,
pageD
}
最后在main.js
引入
//main.js
import modules from './modules/modules'
//将模块装进Store树中
const store = new Vuex.Store({
//全局
state: {},
getters: {},
mutations: {},
actions: {},
//模块
modules
})
//在组件中可以
this.$store.state.pageA
this.$store.state.pageB
this.$store.state.pageC
this.$store.state.pageD
Vuex基本概念的更多相关文章
- 【VUE】8.VUEX核心概念
1. Vuex核心概念主要如下 state : 存储共享数据 mutation: 变更store中的数据,方法,不能异步操作 action: 异步操作,通过触发mutation变更数据 getter: ...
- Vuex 基本概念
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 每一个 Vuex 应用的核心就是 stor ...
- 4.VUEX到底是什么
关于vuex类的新闻最近很多,看到眼热就去查了下资料,然后扯出来一堆flux.redux.state.state之类的概念,以及大型工程必要性之类的.看官方手册也是昏昏然. 然而,我还是弄懂了!我准备 ...
- vue创建状态管理(vuex的store机制)
1:为什么说要是永远状态管理 在使用 Vue 框架做单页面应用时,我们时常会遇到传值,组件公用状态的问题.(子父间传值文章传送门) ,如果是简单的应用,兄弟组件之间通信还能使用 eventBus 来作 ...
- VueJs(14)---理解Vuex
理解Vuex 一.Vuex 是什么? 首先我们来分析一种实际开发中用vue.js的场景,你有n个组件,当你改变一个组件数据的时候需要同时改变其它n个组件的数据,那么我想你可能会对 vue 组件之间的通 ...
- Vuex详解
一.什么是Vuex 官网解释如下: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex ...
- vuex状态管理之学习笔记
概述及使用场景 Vuex 是一个主要应用在中大型单页应用的类似于 Flux 的数据管理架构.它主要帮我们更好地组织代码,以及把应用内的的状态保持在可维护.可理解的状态. 但如果是简单的应用 ,就没有必 ...
- 一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app
一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app 转载 作者:jrainlau 链接:https://segmentfault.com/a/1190000005844155 ...
- Vuex状态管理详解
什么是Vuex 专门为vue应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态(数据),以相应的规则保证状态以一种可预测的方式发生改变 Vuex的作用(什么样的情况下使用Vuex) 多 ...
随机推荐
- 新版蜀山剑侠传3D立体格斗全方位剖析
国人终极格斗<蜀山剑侠传>,突破传统横版格斗"二次元"瓶颈,率先开辟3D立体横版格斗网游先河,实现"有纬度"的空间化立体式全景3D战斗体验!游戏大量 ...
- QuantLib 金融计算——基本组件之 ExchangeRateManager 类
目录 QuantLib 金融计算--基本组件之 ExchangeRateManager 类 概述 Money 类中的汇率转换配置 ExchangeRateManager 函数 如果未做特别说明,文中的 ...
- JavaScript简介和发展史,JavaScript组成和开发工具-乐字节
一.JavaScript简介 JavaScript 是一种具有面向对象能力的.解释型的程序设计语言.更具体一点,它是基于对象和事件驱动并具有相对安全性的客户端脚本语言.它的主要目的是,验证发往服务器端 ...
- Hadoop概念学习系列之Hadoop 生态系统
当下 Hadoop 已经成长为一个庞大的生态体系,只要和海量数据相关的领域,都有 Hadoop 的身影.下图是一个 Hadoop 生态系统的图谱,详细列举了在 Hadoop 这个生态系统中出现的各种数 ...
- web前端与后台数据交互
1.前端请求数据URL由谁来写? 在开发中,URL主要是由后台来写的,写好了给前端开发者.如果后台在查询数据,需要借助查询条件才能查询到前端需要的数据时,这时后台会要求前端提供相关的查询参数,这里的查 ...
- css未知宽度水平居中整理
1.text-align 兼容性很好 .wp {text-align: center;} .test {display: inline;} <ul class="wp"> ...
- IDEA自定义设置快捷键输出你想要的语句!
转载,侵权必删 用Eclipse时间长了, 就习惯之前的快捷键! 当然, IDEA不愧是Java开发的”利器”! 写起代码就是一个字 – “爽”! 建议大家可以去尝试一下! 当然, 在IDEA中输出S ...
- phpmyadmin 出现Table 'root.pma_table_uiprefs' doesn't exist
原文链接:http://zhidao.baidu.com/link?url=ugBKDds94yxWhh_IZ6rZWZYSd2nO555EZ1WMClXRrqL0aKLc-HPDrZVSKZyDaD ...
- Django中对单表的增删改查
之前的简单预习,重点在后面 方式一: # create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象 book_obj=Book.objects.creat ...
- bin&sbin 命令作用
最近需要了解sbin与bin的功能,需要整理一下.一下全部为Ubuntu14里面默认安装的.在这里收集一下,转载请注明出处! bin bash shell bunzip2 .bz2文件的解压缩程序. ...