Vuex核心知识(转)
转:http://www.cnblogs.com/ghost-xyx/p/6380689.html
Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式,它类似于 Redux 应用于 React 项目中,他们都是一种 Flux 架构。相比 Redux,Vuex 更简洁,学习成本更低。希望通过本文帮助还没使用 Vuex 的同学快速上手。
注:本文针对 Vuex 2.0 的语法,目前通过 npm 默认下载的版本为 1.0+ ,想引入 2.0 版本可以通过 script 标签引入。
<script src="https://unpkg.com/vuex@2.0.0"></script>
习惯使用 ES6 中 import 方法的可以暂时通过解构赋值的方式引入 Vuex 中的方法。
import { mapState, mapGetters } from 'Vuex';
// a.js var sex="boy";
var echo=function(value){
console.log(value)
}
export {sex,echo}
//通过向大括号中添加sex,echo变量并且export输出,就可以将对应变量值以sex、echo变量标识符形式暴露给其他文件而被读取到
//不能写成export sex这样的方式,如果这样就相当于export "boy",外部文件就获取不到该文件的内部变量sex的值,因为没有对外输出变量接口,只是输出的字符串。
// b.js
通过import获取a.js文件的内部变量,{}括号内的变量来自于a.js文件export出的变量标识符。
import {sex,echo} from "./a.js"
console.log(sex) // boy
echo(sex) // boy
//替换为:
let { mapState, mapGetters } = Vuex;
Vuex 的核心内容主要就是 State、Getters、Mutations、Actions 这四部分,也非常好理解。
State
首先看如何申明一个 store(仓库)
import Vue from 'Vue';
import Vuex from 'Vuex'; Vue.use(Vuex); let store = new Vuex.Store({
state: {
stateA: 'a',
stateB: 'b',
stateC: 'c'
}
}); console.log(store.state.stateA); // a
在 store 中的 state 对象,可以理解为 Vue 实例中的 data 对象,它用来保存最基本的数据。
在 Vue 中获取 store 中的状态
let app = new Vue({
el: '#demo',
template: `<h1>{{myState}}</h1>`,
computed: {
myState() {
return store.state.stateA;
}
}
});
最简单的方式就是通过 Vue 中的计算属性(computed) 来将 store 中的状态映射为 Vue 的数据。但是当数据多时这种方法明显效率过低,所以 Vuex 中提供了 mapState 方法用于批量映射 store 中的状态。
首先必须在 Vue 中注册 store 选项,这样整个 store 就从根节点注册到 Vue 下的每一个子组件里了。
import { mapState } from 'Vuex'; let app = new Vue({
el: '#demo',
store,
data: {
local: 'L'
},
computed: mapState({
stateA: state => state.stateA,
stateB: 'stateB',
stateC(state) {
return state.stateC + this.local;
}
})
});
上例中,a. 可以通过 ES6 中的箭头函数进行数据的映射,b. 当计算属性的名称与 state 的属性名一致时可能直接通过字符串赋值,c. 当需要引用上下文中的 data 属性时,只能通过常规函数来使 this 生效。
如果所有计算属性的名称都与 state 一致,可以在 mapState 中以数组的方式进行映射。如果 Vue 中已经存在计算属性,可以通过 ES6 的展开操作符 (...) 进行组合。
let app = new Vue({
el: '#demo',
store,
computed: {
local() {
return 'Local';
},
...mapState(['stateA', 'stateB', 'stateC'])
}
});
Getters
当需要对 store 中的数据进行处理,或者需要对处理后的数据进行复用,就可以使用 Getters 来处理,Getters 也可以理解为 Vue 中的计算属性 (computed)。
let store = new Vuex.Store({
state: {
nowDate: new Date()
},
getters: {
dateFormat(state, getters) {
let date = state.nowDate;
return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()} / ${date.getHours()}:${date.getMinutes()}`;
}
}
}); console.log('The time is now:', store.getters.dateFormat); // The time is now: 2017-2-10 / 17:28
getters 接收两个参数,1. state、2. getters 本身,可以引用其他 getters。与 mapState 类似,Getters 也拥有 mapGetters 方法,用于批量映射。
let { mapGetters } from 'Vuex'; let comonent = {
computed: {
...mapGetters([
'nowDate'
])
}
};
Mutations
在 Vue 中,data 值是可以直接被更改的。但是在 Vuex 中,不能直接对 state 进行操作,唯一的方法就是提交 mutation。mutation 可以理解为 Vue 中的 method 事件,只不过调用 mutation 需要特别的方法。
let store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addCount(state) {
state.count ++;
}
}
}); store.commit('addCount'); console.log(store.state.count); // 1
每一个 mutation 都有一个字符串的事件类型和一个回调函数。通常在回调函数中进行状态更改,通过 store.commit 触发事件。
传参
// ...
mutations: {
addCount(state, n) {
state.count += n;
}
} store.commit('addCount', 10);
这种方式有一个问题,一旦参数多了,就必须保证传入的顺序不能出错,可读性也很低。所以通常将参数以对象的形式传入,同时 mutaion 的事件类型字符串也可以使用对象的形式传入。
// ...
mutations: {
addCount(state, params) {
state.count += params.num;
}
} store.commit('addCount', {
num: 10
}); store.commit({
type: 'addCount',
num: 10
});
这里有一个规则需要遵守,在 mutation 中更改 state 应该以新对象替换老对象,不要在直接原对象上直接修改。*熟悉 React 的朋友们应该知道,在使用 setState 更新状态时也是同样的规则。
通过 ES6 的展开操作符可以很容易的完成。
state.obj = { ...state.obj, newState: 123 };
在 Vue 组件中提交 mutaion
this.$store.commit('xxx');
在组件中可以通过上述方法提交 commit,不过 Vuex 提供了 mapMutations 方法用于将 mutation 映射到组件中的 method 中。与 mapState、mapGetters 相似,这里就不再赘述了。
import { mapMutations } from 'vuex' const component = {
// ...
methods: {
...mapMutations([
'addCount' // 映射 this.addCount() 为 this.$store.commit('addCount')
]),
...mapMutations({
add: 'addCount' // 映射 this.add() 为 this.$store.commit('addCount')
})
}
}
mutation 必须是同步函数
我们先试着写一个异步的 mutation ,看看会发生什么。
// ...
mutations: {
asyncAdd(state) {
setTimeout(() => {
state.count ++;
}, 2000);
}
} store.commit('asyncAdd');
经测试,在 mutaion 里进行异步操作也是会生效的,2秒之后 state.count 确实发生改变。
那为什么还要强调 mutation 必须是同步的呢?因为在触发 commit 之后,回调函数还没有被调用,所以这次 mutation 的修改也是无法被调试工具所记录的。
如何对 state 进行异步操作呢,就要使用下面的 Action 了。
Actions
Action 类似于 mutation,不同在于:
1. Action 不直接更改状态,而是提交 mutation
2. Action 可以包含任何异步操作
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addCount(state) {
state.count ++;
}
},
actions: {
asyncAdd(context) {
setTimeout(() => {
context.commit('addCount');
}, 2000);
}
}
})
Action 中的回调函数会接收一个上下文 context 对象,它包含了当前 store 中所有属性和方法,但其不是 store 本身。你可以通过 context.commit 来提交 mutation,也可以通过 context.state 与 context.getters 来获取 state 和 getters。
当需要多次调用 commit 时,可以使用 ES6 的语法对传入的参数进行解构。
// ...
actions: {
asyncAdd({ commit }) {
commit('addCount');
}
}
分发 Action 与传参
Action 是通过 store.dispatch 方法来触发,传参方式与 store.commit 类似。
store.dispatch('asyncAdd'); store.dispatch('asyncAdd', {
num: 10
}); store.dispatch({
type: 'asyncAdd',
num: 10
});
在 Vue 组件中分发 Action
this.$store.dispatch('xxx');
可以使用上述方式,同时 Vuex 中也提供了 mapActions 方法用于批量映射于组件中的 methods 中,与 mapMutations 类似。
import { mapActions } from 'vuex' const component = {
// ...
methods: {
...mapActions([
'asyncAdd' // 映射 this.asyncAdd() 为 this.$store.dispatch('asyncAdd')
]),
...mapActions({
add: 'asyncAdd' // 映射 this.add() 为 this.$store.dispatch('asyncAdd')
})
}
}
组合 Actions
既然 Action 是异步行为,那我们可以使用 ES6 中的 Promise 对象进行组合。
const store = {
actions: {
asyncActionA({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('asyncAdd');
resolve();
}, 2000);
});
},
asyncActionB({ dispatch }, params) {
return dispatch('asyncActionA').then(() => {
console.log('Action complete at: ', params.date);
});
}
}
} store.dispatch('asyncActionB', {
date: (new Date()).getTime() // 2秒后打印 Action complete at: xxxxxxxx (当前时间毫秒数)
});
ES6 中的箭头函数
定义
定义一个箭头函数很简单,基本语法是:
([param] [, param]) => {
statements
} param => expression
param 是参数,根据参数个数不同,分这几种情况:
- () => { ... } // 零个参数用 () 表示;
- x => { ... } // 一个参数可以省略 ();
- (x, y) => { ... } // 多参数不能省略 ();
当然,和普通函数一样,箭头函数也可以使用 ES6 新增的「默认参数」和「剩余参数」( Firefox15+ 开始支持):
var func1 = (x = 1, y = 2) => x + y;
func1(); // 得到 3 var func2 = (x, ...args) => { console.log(args) };
func2(1,2,3); // 输出 [2, 3]
箭头函数允许多行语句或者单行表达式作为函数体。多行语句要用 {} 括起来;单行表达式不需要 {},并且会作为函数返回值:
x => { return x * x }; // 函数返回 x * x
x => x * x; // 同上一行
x => return x * x; // SyntaxError 报错,不能省略 {}
x => { x * x }; // 合法,没有定义返回值,返回 undefined
箭头函数也是 JS 函数的一种,所以之前的 instanceof 和 typeof 依然可用:
var func1 = () => {};
func1 instanceof Function; // true var func2 = () => {};
typeof func2; // "function"
Vuex核心知识(转)的更多相关文章
- Vuex核心知识(2.0)
Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式,它类似于 Redux 应用于 React 项目中,他们都是一种 Flux 架构.相比 Redux,Vuex 更简洁,学习成本更低.希望 ...
- 前端知识扫盲-VUE知识篇一(VUE核心知识)
最近对整个前端的知识做了一次复盘,总结了一些知识点,分享给大家有助于加深印象. 想要更加理解透彻的同学,还需要大家自己去查阅资料或者翻看源码.后面会陆续的更新一些相关注知识点的文章. 文章只提出问题, ...
- 网络基础知识、ASP.NET 核心知识(1)*
为什么要写网络? 我原本的计划是这样的,连续两天梳理ASP.NET开发的核心知识.说到这呢,有人问了.“不是说好了做ASP.NET笔记吗?为啥要写网络基础知识?是不是傻?” 原因是这样的.作为网站开发 ...
- Python 编程核心知识体系(REF)
Python 编程核心知识体系: https://woaielf.github.io/2017/06/13/python3-all/ https://woaielf.github.io/page2/
- Cookie详解、ASP.NET核心知识(7)
无状态的http协议 1.回顾http协议 Http协议是请求响应式的,有请求才有响应,是无状态的,不会记得上次和网页“发生了什么”. 关于http协议的这种特点,黑兔在前面的这三篇博文中进行了详细的 ...
- 《Maven实战》关联实际工作的核心知识
通读了<Maven实战>这本书,由于在实际的工作中,对其有一定的操作上的经验.因此,再回头去通读这本书,就能够更加精准的把握里面的核心知识了. 以下我主要从两点去介绍之—— 1> m ...
- Linux(1)- 服务器核心知识、Linux入门、VMware与centeos安装、远程连接linux、linux基本命令使用
一.服务器核心知识 1.电脑和电脑的硬件组成 现在的人们几乎无时无刻不在使用着电脑!不管是桌上型电脑(桌机).笔记型电脑(笔电).平板电脑,还是智慧型手机等等,这些东西都算是电脑.虽然接触这么多,但是 ...
- HTML中DOM核心知识有哪些(带实例超详解)
HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...
- Java并发编程核心知识体系精讲
第1章 开宗明义[不看错过一个亿]本章一连串设问:为什么学并发编程?学并发编程痛点?谁适合学习本课?本课程包含内容和亮点?首先4大个理由告诉你为什么要学,其实源于JD岗位要求就不得不服了.其次5个痛点 ...
随机推荐
- 自己动手开发更好用的markdown编辑器-06(自动更新)
这里文章都是从个人的github博客直接复制过来的,排版可能有点乱. 原始地址 http://benq.im/2015/05/12/hexomd-06/ 文章目录 1. 自动更新方案 2. 实现 ...
- TensorFlow学习笔记 速记2 报错:failed call to cuDevicePrimaryCtxRetain: CUDA_ERROR_INVALID_DEVICE
版本: tensorflow-gpu 原因: 在创建session时没有使用我想让它用的gpu 解决方案: 1. 在python程序中: import os os.environ["CUDA ...
- window安装rabbitmq
Rabbit MQ 是建立在强大的Erlang OTP平台上,因此安装Rabbit MQ的前提是安装Erlang.通过下面两个连接可以下载安装最新的版本: 下载并安装Eralng OTP For Wi ...
- hdu5305Friends dfs
//给一个无向图 , 每条边能够是online边也能够是offline边,问 //有多少种方法使得每一个节点的online边和offline边一样多 #include<cstdio> #i ...
- python 转化文件编码 utf8
使用visual studio最大的一个问题就是文件编码问题,当文件中有中文时,visual studio 会默认为区域编码,也就是gb2312,如果想跨平台或者不用vs编译的话,就会因为编码问题导致 ...
- 配置LANMP环境(5)-- 安装NGINX与配置
安装nginx yum install nginx 若提示找不到nginx,则在软件源中添加nginx的软件源文件: vim /etc/yum.repos.d/nginx.repo 添加如下内容: [ ...
- JVM架构和GC垃圾回收机制详解
JVM架构图分析 下图:参考网络+书籍,如有侵权请见谅 (想了解Hadoop内存溢出请看:Hadoop内存溢出(OOM)分类.参数调优化) JVM被分为三个主要的子系统 (1)类加载器子系统(2)运行 ...
- 【转】 详细介绍windows下使用python pylot进行网站压力测试
windows下使用python进行网站压力测试,有两个必不可少的程序需要安装,一个是python,另一个是pylot.python是一个安装软件,用来运行python程序,而pylot则是pytho ...
- 嵌入式开发之davinci--- 8168 总的roi 编码
http://bbs.61dsp.com/forum.php?mod=viewthread&tid=767
- Android 图片压缩的方法大全
public static Bitmap revitionImageSize(String path) throws IOException { BufferedInputStream in = ne ...