转: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核心知识(转)的更多相关文章

  1. Vuex核心知识(2.0)

    Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式,它类似于 Redux 应用于 React 项目中,他们都是一种 Flux 架构.相比 Redux,Vuex 更简洁,学习成本更低.希望 ...

  2. 前端知识扫盲-VUE知识篇一(VUE核心知识)

    最近对整个前端的知识做了一次复盘,总结了一些知识点,分享给大家有助于加深印象. 想要更加理解透彻的同学,还需要大家自己去查阅资料或者翻看源码.后面会陆续的更新一些相关注知识点的文章. 文章只提出问题, ...

  3. 网络基础知识、ASP.NET 核心知识(1)*

    为什么要写网络? 我原本的计划是这样的,连续两天梳理ASP.NET开发的核心知识.说到这呢,有人问了.“不是说好了做ASP.NET笔记吗?为啥要写网络基础知识?是不是傻?” 原因是这样的.作为网站开发 ...

  4. Python 编程核心知识体系(REF)

    Python 编程核心知识体系: https://woaielf.github.io/2017/06/13/python3-all/ https://woaielf.github.io/page2/

  5. Cookie详解、ASP.NET核心知识(7)

    无状态的http协议 1.回顾http协议 Http协议是请求响应式的,有请求才有响应,是无状态的,不会记得上次和网页“发生了什么”. 关于http协议的这种特点,黑兔在前面的这三篇博文中进行了详细的 ...

  6. 《Maven实战》关联实际工作的核心知识

    通读了<Maven实战>这本书,由于在实际的工作中,对其有一定的操作上的经验.因此,再回头去通读这本书,就能够更加精准的把握里面的核心知识了. 以下我主要从两点去介绍之—— 1> m ...

  7. Linux(1)- 服务器核心知识、Linux入门、VMware与centeos安装、远程连接linux、linux基本命令使用

    一.服务器核心知识 1.电脑和电脑的硬件组成 现在的人们几乎无时无刻不在使用着电脑!不管是桌上型电脑(桌机).笔记型电脑(笔电).平板电脑,还是智慧型手机等等,这些东西都算是电脑.虽然接触这么多,但是 ...

  8. HTML中DOM核心知识有哪些(带实例超详解)

    HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...

  9. Java并发编程核心知识体系精讲

    第1章 开宗明义[不看错过一个亿]本章一连串设问:为什么学并发编程?学并发编程痛点?谁适合学习本课?本课程包含内容和亮点?首先4大个理由告诉你为什么要学,其实源于JD岗位要求就不得不服了.其次5个痛点 ...

随机推荐

  1. AF_UNIX和AF_INET域的socket在epoll中的差异

    1.AF_UNIX & SOCK_STREAM 1.1 accept_socket BLOCK EPOLLIN|EPOLLET 1.2 accept_socket NON-BLOCK EPOL ...

  2. 使用GraphicsMagick/ImageMagick批量对图片瘦身

    GrahpicsMagick: find . -iname "*.jpg" -exec gm convert -strip +profile "*" -qual ...

  3. 配置AutoMapper映射规则《转》

    配置AutoMapper映射规则 AutoMapper是基于约定的,因此在实用映射之前,我们需要先进行映射规则的配置. public class Source { public int SomeVal ...

  4. python第二周数据类型 字符编码 文件处理

    第一数据类型需要学习的几个点: 用途 定义方式 常用操作和内置的方法 该类型总结: 可以存一个值或者多个值 只能存储一个值 可以存储多个值,值都可以是什么类型 有序或者无序 可变或者不可变 二:数字整 ...

  5. 使用Squid搭建HTTPS代理服务器

    由于经常去的一些国外网站如Google.Blogspot.Wordpress被"出现了技术问题",访问不了,于是我在自己的DigitalOcean云主机上搭建了一个 Squid代理 ...

  6. Discuz二次开发手册

    Discuz文件说明,有助于discuz爱好者,进行自己的开发,在这里提供方便 admincp.php——后台系统设置主程序文件,一般只处理菜单的显示的访问权限,不处理管理控制. ajax.php—— ...

  7. Spring MVC列表多选框

    以下示例显示如何在使用Spring Web MVC框架的表单中使用列表框(Listbox).首先使用Eclipse IDE来创建一个WEB工程,实现一个让用户可选择自己所善长的技术(多选)的功能.并按 ...

  8. Eclipse 任务管理

    管理任务 在Eclipse中用TODO标签管理任务,利用这个功能可以方便地将项目中一些需要处理的任务记录下来. 我们可以在 Java 代码中的注释添加 TODO 单词来标记一个任务,任务可以通过 Ta ...

  9. iOS 阿里百川SDK集成注意点

    百川SDK是阿里系OneSDK的终极版本,里面包含了所有的阿里系的基本所有的SDK,集成的时候你只需要勾选对应的你需要的模块,然后生成对应的SDK即可,百川主要是针对帮助APP开发者在各种场景下快速. ...

  10. Java手记

    由于腾讯的MTA只有JAVA的demo,为了测试用php实现的加密算法是否正确,所有只能运行一下Java 配置环境:http://www.runoob.com/java/java-environmen ...