一、 Vuex用法
Vuex核心包括state、mutatios、actions、getters四个部分。
Vuex.Store 构造器选项
state
-
类型:
Object | FunctionVuex store 实例的根 state 对象。
如果你传入返回一个对象的函数,其返回的对象会被用作根 state。这在你想要重用 state 对象,尤其是对于重用 module 来说非常有用。
mutations
-
类型:
{ [type: string]: Function }在 store 上注册 mutation,处理函数总是接受
state作为第一个参数(如果定义在模块中,则为模块的局部状态),payload作为第二个参数(可选)。
actions
-
类型:
{ [type: string]: Function }在 store 上注册 action。处理函数总是接受
context作为第一个参数,payload作为第二个参数(可选)。
getters
-
类型:
{ [key: string]: Function }用于对
state中的值进行二次加工,作用类似于Vue中的Computed。
参考:Vuex官网
二、Vuex的核心
- 首先创建store.js文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
count: 0
}
})
- 然后在main的js中引入并注册store
new Vue({
store,
render: h => h(App),
}).$mount('#app')
- 此时便可在页面中使用vuex中存储的数据
<template>
<div id="app">
<div>{{ $store.state.count }}</div>
</div>
</template>
如图:
- 上述为vuex中数据的使用,下面可以可以开始使用vuex的一些内置方法,将store.js中代码修改为如下所示。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
count: 0
},
actions: {
increment(context, a) {
context.commit('increment', a)
}
},
mutations: {
increment(state, num) {
state.count += Number(num)
}
},
getters: {
countResult: state => {
return state.count + '元'
}
}
})
- 此时我们可以通过
action中的方法来触发mutatios中的方法来修改state中的值,也可以通过getters来获取对state二次处理后的值。
<template>
<div id="app">
<div>{{ $store.state.count }}</div>
<div>{{ $store.getters.countResult }}</div>
<button @click="add">点击</button>
</div>
</template>
<script>
export default {
name: 'App',
mounted() {
console.log(this.$store.getters.countResult)
},
methods: {
add() {
this.$store.dispatch('increment', 10)
}
},
}
</script>
- 结果如图:
-
以上为Vuex的基本用法,接下来我们来手写其核心部分。
- 首先,我们根据Vuex的使用方式
Vue.use(Vuex)可知,Vuex是Vue的插件。所以,我们需要知道如何自定义插件。
- 参考:vue插件
- 根据文章可知,插件可以为函数,或者为具有install方法的对象。Vue在注册插件的时候会调用插件函数或者插件的install函数。
- 首先,我们根据Vuex的使用方式
Vue.use = function(plugin){
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
if(installedPlugins.indexOf(plugin)>-1){
return this;
}
<!-- 其他参数 -->
const args = toArray(arguments,1);
args.unshift(this);
if(typeof plugin.install === 'function'){
plugin.install.apply(plugin,args);
}else if(typeof plugin === 'function'){
plugin.apply(null,plugin,args);
}
installedPlugins.push(plugin);
return this;
}
- 如上所示,Vue的use方法会根据插件类型来进行不同方式的调用。
3.所以Vuex应为函数或具有install方法的对象。我们新建文件夹myVuex.js。
const install = () =>{}
const myVuex = {
install
}
export default myVuex
- 此时myVuex具有install方法,所以是可以被注册为插件的。install方法可以说是初始化Vuex的方法。我们知道在组件中使用Vuex需要通过this.store,所以我们需要在install中为Vue实例挂载$store。
const install = (Vue) => {
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
},
})
}
- 使用混入,在每一个组件初始化时调用beforeCreate钩子来挂载$store。
- 根组件在main.js中通过new Vue({ store, render: h => h(App), }).$mount('#app')已经挂载。
- 根据我们在store.js中创建store实例是通过new Vuex.Store来创建。所以我们可知Store为挂载在Vuex上的类。所以我们可以为我们的vuex挂载Store。
const install = (Vue) => {
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.store) {
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
},
})
}
class Store {
constructor(config) {
}
}
const myVuex = {
install,
Store,
}
- 根据store.js创建实例可以看出,初始化时会给Store传入state、actions、mutations、getters等配置。所以我们可以在Store类的constructor中获取配置参数,然后进行逐步分析。
- 首先是state,state为数值,由于Vuex的state是具有响应式的,所以我们需要通过new Vue实例来借用Vue中的data会被自动注册为响应书数据来实现state的响应式。注册响应式后我们需要通过this.$store.vm.state来获取state,这是不规范的,Vuex中并不是这样取值,所以我们需要使用get函数,当get state值时,返回this.vm.state。
constructor(config) {
this.vm = new Vue({
data: {
state: config.state
}
})
}
get state() {
return this.vm.state
}
9.然后我们来分析getters,getters的调用为this.$store.getters.a。所以Store需要具有getters属性,而且getters属性是对state的二次处理。如下所示。
constructor(config) {
this.vm = new Vue({
data: {
state: config.state
}
})
let getters = config.getters || {}
this.getters = {}
Object.keys(getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {
get: () => {
return getters[getterName](this.state)
}
})
})
}
10.接下来是actions,我们需要通过dispatch来调用actions,然后通过actions来调用commit方法来出发mutations进而修改state。所以Stote类中还需要dispatch方法来调用actions
- 首先我们来对actios进行注册
constructor(config) {
this.vm = new Vue({
data: {
state: config.state
}
})
// 注册actions
this.actions = config.actions
// 注册mutations
this.mutations = config.mutations
let getters = config.getters || {}
this.getters = {}
Object.keys(getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {
get: () => {
return getters[getterName](this.state)
}
})
})
}
- 然后我们注册dispatch方法来调用actions中的方法。
dispatch(){
// 第一个参数为所要调用的action名称,args中为其他所有参数
const [method, ...args] = arguments
// actions方法中第一个参数为this.state
this.actions[method](this, args)
}
- mutations与actions同理,不同的是mutation方法中接收的第一个参数为state
commit() {
const [method, ...args] = arguments
this.mutations[method](this.state, args)
}
以上是对Vuex用法及核心原理的介绍与实现,如有错误还望批评指正,是和大家分享知识也是对自己学习的总结,感谢阅读。