Vuex 是什么?
首先我们可以看看vuex官方文档关于vuex的概念:
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state) 。Vuex 和单纯的全局对象有以下两点不同:
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
个人理解: vuex就是一个公共的资源共享库,可以供各个组件使用,方便组件之间的通信
Vuex原理理解
- Vuex本质上是一个对象
- Vuex对象有两个方法,一个是install方法,一个是Store类
- Store类里面有commit,dispatch这些方法
要怎么根据核心原理来实现vuex呢
首先看看vuex是怎么被使用的
store/index.js
import Vue from 'vue'
// import Vuex from 'vuex'
import Vuex from './myVuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
num: 1
},
mutations: { // mutations里面的方法天生就具备参数,且参数为state, 这里面的方法可以改动state
incre(state, arg) {
state.num += arg
}
},
actions: { //Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
asyncIncre({commit}, arg) { // actions里面的函数天生就具备一个参数,为一个对象{commit} (vuex的上下文)
setTimeout(() => {
commit('incre', arg)
}, 1000)
}
},
modules: {
},
getters: { // 派生出一些状态, 相当于组件中的 computed
getNum (state) { //getters里面的方法天生就具备参数,且参数为state, 这里面的方法可以改动state
return state.num*10
}
}
})
根据理解的vuex核心原理来实现一个vuex
store/myVue.js
// vuex 是一个对象,里面有个方法,一个是install,一个是Strore。首先定义store对象这里面挂载两个方法,install和Store
import Vue from 'vue' // 引入vue
class store {
constructer(options) {
// state 的实现
this.vm = new Vue({ // 利用vue的data数据源,让state变成响应式
data: {
state: options.state || {}
}
}),
// mutations 的实现
let mutations = options.mutations || {}
this.mutations = {}
Object.keys(mutations).forEach(mutationName => { // 得到mutations对象里面的keys
this.mutations[mutationName] = (arg) => { //
mutations[mutationName](this.state, arg) // 调用
}
}),
// actions 的实现
let actions = options.actions
this.actions = {}
Object.keys(actions).forEach(actionName => {
this.actions[actionName] = (arg) => {
actions[actionName](this, arg) // this是整个vue实例
}
})
// getters的实现
let getters = options.getters || {}
this.getters = {}
Object.keys(getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, { // 数据拦截
get: () => { // 得到这个变量,可以用它的变量名显示
return getters[getterName](this.state)
}
})
})
}
// 用来调用actions里面的方法
dispatch(method, arg) {
this.actions[method](arg)
}
// 用来调用mutations里面的方法
commit = (method, arg) => { // 注意作用域问题 this
console.log(this);
this.mutations[method](arg)
}
get state() { // 函数前面加get,当我们要取函数内部的返回值时,只需要写函数名state就可以
return this.vm.state
}
}
//因为vuex会被vue.use(vuex)
// 又因为被use的需规则要:
// 1. Vue.use()接受一个参数,可以是对象,也可以是函数,如果是对象,该对象内必须具备install方法
// 2. use会将vue实例作为参数传递给install函数,且调用install函数
// 3. install方法被同一个插件多次调用时,插件也只会安装一次
// 所以vuex需要具备一个install方法,而且插件安装在new Vue 之前
let install = function(Vue) {
Vue.mixin({
beforeCreate() { // vue初始化好
// 如何把vuex实例$store分发给所有的组件使用
if (this.$options && this.$options.store) { // this.$options用来获取页面根组件
this.$store = this.$options.store // 往vue身上挂载了$store
} else { // 子组件
this.$store = this.$parent && this.$parent.$store
}
},
})
}
let Vuex = {
Store,
install
}
export default Vuex // 抛出
可以对实现的vuex进行测试
app.vue
<template>
<div id="app">
{{this.$store.state.num}}
<p>{{this.$store.getters.getNum}}</p>
<button @click="add">add</button>
<button @click="asyncadd">add2</button>
</div>
</template>
<script>
export default {
methods: {
add() {
this.$store.commit('incre', 1)
},
asyncadd() {
this.$store.dispatch('asyncIncre', 2)
}
},
}
</script>
总结
以上便是我对vuex的理解,如有不对指出希望大家能够指正,谢谢大家