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个痛点 ...
随机推荐
- python统计订单走势
#coding=utf-8 import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotl ...
- JPA动态查询封装
一.定义一个查询条件容器 /** * 定义一个查询条件容器 * * @param <T> */ public class Criteria<T> implements Spec ...
- poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #includ ...
- 分布式服务框架 Zookeeper(四)官方编程指南
握草,是不是加了官方两个字就可以唬人了. 使用ZooKeeper开发分布式应用 简介 这篇文档是为了那些想利用ZooKeeper的协调服务来构建分布式应用的开发人员而写滴,不相干的走一边去哈.在这儿有 ...
- Linux 脚本点滴知识积累
1.以openwrt中的/etc/hotplug.d/button/00-button为例 . /lib/functions.sh do_button () { local button ---- ...
- JSP/Servlet环境配置
下载安装JDK并配置环境变量 这里我下载安装的是jdk-7u51-windows-i586,如果你没有请到Oracle官网下载: [我的电脑]-[高级系统设置]-[环境变量]-系统变量中的Path添加 ...
- Spring MVC错误处理
以下示例显示如何在使用Spring Web MVC框架的表单中使用错误处理和验证器.首先使用Eclipse IDE来创建一个WEB工程,实现一个输入用户信息提交验证提示的功能.并按照以下步骤使用Spr ...
- cocos2dx-3.0(前言)
说了好久,告诉自己要開始学cocos2dx(在心理里告诉了好久),然后养成良好习惯,记录自己学习cocos2dx的过程.一个是怕自己忘记.还有一个是更加让自己理解透彻(或许哪天我写的好了,组合一下出一 ...
- Laravel5.1 路由 -基础
什么是路由? 大K简单的说下,路由是用户访问我们程序的一个入口,比方说 你在浏览器输入:www.myblogs.com/create 就会打开一个页面,我们接收到这一个请求后后台需要做一些事儿来反馈给 ...
- FreeMarker / S2SH 各种报错解决方案
1. org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of ...