vuex入门
在这里先推荐一个在线编辑工具codesandbox.io,不同于codepen这类的在线代码运行工具,它可以创建一个基本的前端项目,所以对于vue、react的用户比较友好:
它是干嘛的?
它用于对复杂应用进行状态管理,官方称其为状态管理模式
这看起来和EventBus有点相似,但是,一般来说eventbus是用来绑定和触发事件的,并不关心数据的采集。
vuex的核心是store对象,它是一个容器,包含了应用中的状态,与之关联的组件可以通过它分享需要共享的数据。它的基本特征(官网说明):
1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
从一个官方的demo来了解一下vuex:
<div id="app">
<p>{{ count }}</p>
<p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</p>
</div>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++,
decrement: state => state.count--
}
})
new Vue({
el: '#app',
computed: {
count() {
return store.state.count
}
},
methods: {
increment() {
store.commit('increment')
},
decrement() {
store.commit('decrement')
}
}
})
</script>
在上面的demo中,我们要管理的状态变量是count,如果要修改它的值,我们可以显示地提交mutations
vuex有四大特征属性:
- state: 用来数据共享存储
- mutations: 用来注册改变数据状态
- getters: 用来对共享的数据进行过滤操作
- actions: 异步修改共享数据
它们都有对应的辅助函数
// store.js
const store = new Vuex.Store({
state,
mutations,
actions,
getters
})
vuex的数据是单向流动的,运作的流程和原理:
- vue组件通过dispatch来触发vuex的actions
- vuex的actions触发自身内部的mutations
- mutations触发内部的数据源state
- 数据源state反过来渲染vue组件
state
state内包含需要在应用内共享的数据。假如在state内部有很多变量,我们可以用mapState来辅助操作:
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
name: state => state.name,
age: state => state.age,
id: state => state.id
})
}
}
或者也可以将箭头函数写成数组的形式:
computed: {
...mapState(['name', 'age', 'id])
}
demo:
<div id="app">
<div>
<child></child>
</div>
</div>
<script>
Vue.use(Vuex)
const mapState = Vuex.mapState;
const store = new Vuex.Store({
state: {
name: 'Tom',
age: '18',
id: '20'
}
})
const child = {
template: `<div><p>{{name}} - {{age}} - {{id}}</p></div>`,
computed:{
...mapState([
'name',
'age',
'id'
])
}
}
new Vue({
el: '#app',
store: store,
components: {child},
mounted() {
console.log(this.$store.state.name);
console.log(this.$store.state.age);
console.log(this.$store.state.id);
}
})
</script>
关于如何使用mapState的使用和实现可以参考:vue mapState函数原理分析
mutations
mutations负责直接修改存储状态,其内部的方法总是以state作为第一个参数。激活它内部方法时,不能直接调用mutations handler,需要commit触发。在commit的第一个参数当然是对应的mutations handler,第二个参数被称为mutations的载荷(payload),多数情况下它应该是一个对象:
mutations: {
increment(state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 1
})
// 或者我们可以使用对象风格的commit方式,这样commit传入的参数就是一个对象,这样我们能够更加容易地区分mutations事件类型
store.commit({
type: 'increment',
amount: 1
})
用常量来替代mutations事件类型
// mutation-type.js
export const MUTATION = 'MUTATION'
// store.js
import Vuex from 'vuex'
import { MUTATION } from './mutation-type'
const store = new Vuex.Store({
state: { ... },
mutations: {
[MUTATION](state) {
// ...
}
}
})
actions
actions提交的是mutations操作,并且它是异步的。它可以访问到上下文对象(context),通过context,可以访问到state(context.state)、getters(context.getters)和commit(context.commit)
// mutations.js
DELETE_TODO: (state, payload) => {
let index = state.todos.findIndex(todo => todo.id === payload);
state.todos.splice(index, 1)
}
//actions.js
deleteTodo: (context, payload) => {
context.commit('DELETE_TODO', payload)
}
// 触发的动作
deleteTodo: function(id) {
this.$store.dispatch("deleteTodo", id);
}
actions也有辅助函数mapActions
:
...mapActions({
add: 'add'
})
比如我们要访问到commit函数:
// store.js
const actions = {
add(context, number) {
context.commit('ADD', number)
}
}
getters
getters类似计算属性,主要用来负责一些计算操作,它的第一个参数也是state。类似于state,getters也可以用一个辅助函数mapGetters
,使用方法类似,不展开
从一个vue-todo的demo来入门vuex操作:
See the Pen vue-todo by simon (@simonchen) on CodePen.