Vuex从入门到精通(一)
状态管理
状态的初始化
状态管理,我们应该并不陌生。
举个例子,超市里新进了一批商品,管理员给这些商品分类,建立索引,然后按照顺序放入货架的过程就是最简单的状态管理。
let goods1 = {
category: 'fruit',
name: 'apple',
quantity: 5
}
let goods2 = {
category: 'supplies',
name: 'toothbrush',
quantity: 5
}
let goods3 = {
category: 'clothes',
name: 'sweater',
quantity: 5
}
简单归类后 :
let shop = {
goods: {
fruit: [{ name: 'apple', quantity: 5 }],
supplies: [{ name: 'toothbrush', quantity: 5 }],
clothes: [{ name: 'sweater', quantity: 5 }]
}
}
这样,当我们需要某一商品时,很容易根据类目检索到这个商品 :
console.log(shop.goods.fruit.find(f => f.name === 'apple'))
//-> { name: 'apple', quantity: 5 }
状态的改变
当有顾客前来购买商品时,我们需要类似的操作来减少被购买商品的数量 :
shop.goods.fruit.find(f => f.name === 'apple').quantity --
然而在成千上万的交易量背后,你不知道这些商品被购买的详细情况,你甚至不知道上周卖出了多少苹果,你也就无从得知下周该进多少。
所以你需要一个账目来记录商品购买明细 :
let account = {
appleSold (value) {
console.log("apple sold " + value)
shop.goods.fruit.find(f => f.name === 'apple').quantity -= value
}
}
当卖出苹果时,POS机“滴”一声,记录生成了 :
account.appleSold (5)
//-> apple sold 5
最简单的store
于是,我们得到了一个最简单的store :
let shop = {
goods: {
fruit: [{ name: 'apple', quantity: 5 }],
supplies: [{ name: 'toothbrush', quantity: 5 }],
clothes: [{ name: 'sweater', quantity: 5 }]
},
account: {
appleSold (value) {
console.log("apple sold " + value)
shop.goods.fruit.find(f => f.name === 'apple').quantity -= value
},
funcN () { }
}
}
由此可知,状态管理可以帮助我们更友好的改变状态,同时,跟踪状态变化的轨迹。
Vue(x) er 须知
开始
Vuex 官方文档:
https://vuex.vuejs.org/zh-cn/getting-started.html
Vuex最核心的概念 :
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
下面对此拓展:
对象引用
下面这两段代码将输出什么? 先不要往下看, 自己写一下
let store = {
state: {
msg: "welcome"
}
}, copy = store.state;
store.state = {
hello: "world"
};
console.log(Object.keys(copy));
let store = {
state: {
msg: 'welcome'
}
}, copy = store.state;
store.state.hello = "world";
console.log(Object.keys(copy))
结果如下(如果你都答对了,那么理解和上手Vuex将会很轻松) :
//-> ["msg"]
//-> ["msg", "hello"]
提交和分发
vuex 只是一个工具,或许过了这段时间,过了这个项目,你就不会再用它。
我们要记住的是它留给我们的启示:
不要直接更改状态, 而是通过提交(commit)和分发(dispatch)的方法通知管理者改变对象状态,这是大型项目和复杂状态管理的最佳实践。
Vuex 核心概念
一个完整的 Vuex Store
/**
* index.js
*/
import axios from 'axios'
const store = new Vuex.Store({
state: {
counter: 0
},
getters: {
counter: state => state.counter
},
// 可处理异步请求, dispatch 触发
actions: {
askPermission ({commit}) {
axios.get('/url').then((res) => {
if(res.data.permission)
commit('addCounter')
}).catch((err) => {
console.log('Error: in process "Ask permission".n Detailed: ' + err)
})
}
},
// 同步, commit 触发
mutations: {
addCounter (state) {
state.counter ++
}
}
})
PS: 仔细研究一下 dispatch & actions, commit & mutations, 是否有一种似曾相识的感觉?
Look, 看这对 emit & on (事件机制),同样的事件类型,同样的回调函数。
State
单一状态树
Vuex使用单一状态树,一个state对象包含全部应用层状态,使得一个应用只有唯一数据源(SSOT, Single Source of Truth)
这对模块化并不造成影响
state: {
moduleA: {
},
moduleB: {
}
}
Getter
state: {
prop: ''
}
你可以使用store.state.prop直接读取状态的值, 当然也可以使用Getter :
getters: {
prop = state => state.prop
}
使用Getter的好处在于,你可以从state中派生出一些状态 :
getters: {
prop = state => state.prop,
fixedProp = state => state.prop || '暂无'
}
Mutation
Vuex 中的 mutation 类似于事件,有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),回调函数的接受state作为第一个参数,我们在这里修改状态(state)
state: {
counter: 0
},
mutations: {
addCounter (state) {
state.counter ++
},
addCounter (state, payload) {
state.counter += payload.value
}
}
通过 commit 通知状态变化
store.commit('addCounter')
store.commit('addCounter', {value: 1})
Action
类似于mutation,不同在于
- 只能通过 commit mutation 通知状态变化
- mutation 只能包含同步操作,而 action 可以包含异步操作(比如, 在这里可以执行ajax请求)
actions: {
askPermission ({commit}) {
axios.get('/url').then((res) => {
if(res.data.permission)
commit('addCounter')
}).catch((err) => {
console.log('Error: in process "Ask permission".n Detailed: ' + err)
})
},
askPermission ({commit}, payload) {
axios.get('/url', { params:payload }).then((res) => {
if(res.data.permission)
commit('addCounter')
}).catch((err) => {
console.log('Error: in process "Ask permission".n Detailed: ' + err)
})
}
}
通过 dispatch 通知状态变化
store.dispatch('askPermission')
store.dispatch('askPermission', { author: "lonelydawn" })
Module
Vuex 允许我们将store分割成模块,每个模块拥有自己的state, mutation, action, getter, 甚至是嵌套子模块 :
const store = new Vuex.Store({
modules: {
a: {
state: {},
mutations: {
addCounter(state) {}
},
actions: {},
getters: {}
},
b: {
namespaced: true, // 建立命名空间
state: {},
mutations: {
addCounter(state) {}
},
actions: {}
}
}
})
store.state.a
store.state.b
// 提交 给 模块 a 的 mutations
store.commit('addCounter')
// 提交 给 模块 b 的 mutations
store.commit('b/addCounter')
最后
Vuex 的基本用法已经介绍完了。
相关内容 :
官方文档: https://vuex.vuejs.org/zh-cn/
官方实例: https://github.com/vuejs/vuex/tree/dev/examples
在下列内容中, 我将 演示如何使用 vue + vuex 以及其他常用组件从入门到实战。
- 《Redis设计与实现》读书笔记(十三) ——Redis数据库其他内容与总结
- 《Redis设计与实现》读书笔记(十四) ——Redis RDB文件创建、载入与自动保存原理
- 框架 | Spark中的combineByKey
- 《Redis设计与实现》读书笔记(十五) ——Redis AOF持久化原理与实现
- PHP CodeBase: 生成N个不重复的随机数
- PHP转义Json里的特殊字符的函数
- PHP使用SOAP调用.net的WebService问题
- 框架 | spray-routing的核心流程
- 高通msm8909耳机调试
- 了解PHP中Stream(流)的概念与用法
- 动态绑定与静态绑定
- Android4.0 声卡配置-高通msm8916移植
- PHP安全:session劫持的防御
- 函数式非凡的抽象能力
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android中buildToolVersion与CompileSdkVersion的区别
- Glide用法与技巧以及优秀库的推荐
- Android整理好的图片压缩工具类
- Android Studio获取网络JSON数据并处理的方法
- Android使用ViewPager快速切换Fragment时卡顿的优化方案
- 在Android打包中区分测试和正式环境浅析
- django 多数据库及分库实现方式
- Python气泡提示与标签的实现
- Django之choices选项和富文本编辑器的使用详解
- Android使用RSA加密和解密的示例代码
- Android布局之帧布局FrameLayout详解
- Okhttp3实现爬取验证码及获取Cookie的示例
- Android监听系统来电并弹出提示窗口
- 你该知道的Gradle配置知识总结
- Android布局之绝对布局AbsoluteLayout详解