一、组件常用通信方式
1、 props和$emit
2、通过$parent,$root,$children, $refs
3、$attrs 和 $listeners
4、provide和inject
5、事件总线eventbus
6、vuex:Vuex 集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化。
二、五个属性
- states:vuex的基本数据,用来存储变量,每当变量变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM
- getters:相当于store的计算属性
- mutations:更改 Vuex 的 store 中的状态,必须是同步函数
- actions:异步操作,Action 提交的是 mutation,而不是直接变更状态
- modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
三、需求分析
- 实现一个插件,声明store类,挂载$store
- 创建响应式state,保存getters,mutations,actions
- 实现commit根据用户传入type执行对应mutation
- 实现dispatch根据用户传入type执行对应action,同时传递上下文
- 实现getters,按照getters定义对state做派生
四、准备工作
- 创建一个vue项目,安装vuex;
- 创建一个store/index.js文件,内容如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter: 0
},
getters: {
doubleCounter(state) {
return state.counter * 2
}
},
mutations: {
add(state) {
state.counter++
}
},
actions: {
// 解构上下文
add({ commit }) {
setTimeout(() => {
commit('add')
}, 1000);
}
},
modules: {}
})
- 根节点注入store,在main.js文件中添加如下代码;
import store from './store'
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
- 最后在页面中添加测试代码
<p @click="$store.commit('add')">counter:{{$store.state.counter}}</p>
<p @click="$store.dispatch('add')">async counter:{{$store.state.counter}}</p>
<p>double counter:{{$store.getters.doubleCounter}}</p>
- 在store同一级下,创建xStore文件夹,添加文件index.js和xvuex.js,其中在xvuex.js中实现Store类。然后把项目中所有用到store的,都换成xstore,vuex换成xvuex。
五、实现自己的Store类
- 声明Store类
- 实现install方法(采用mixin方法获得store实例)
function install(_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate() {
if(this.$options.store) {
Vue.property.$store = this.$optins.store
}
}
})
}
- state的数据是一个响应式数据,可以使用new Vue(),其中data给的值是传进来的state对象;
class Store {
constructor(options) {
this.state = new Vue({
data: options.state
})
}
}
至此,实现了创建一个响应式state。
- 实现commit(接收两个参数,一个是type,一个是payload,type是mutation的类型,payload是参数)
commit(type, payload) {
const entry = this._mutations[type]
if(entry) {
entry(this.state,payload)
}
}
- 实现dispatch,类似于commit
dispatch(type, payload) {
const entry = this._actions[type]
if(entry) {
entry(this,payload)
}
}
- 实现getters,通过computed来实现,代码如下:
const computed = {};
this.getters = {}; //暴露getters,以供用户获取
const store = this;
Object.keys(this.getterWrapper).forEach(k => {
let fn = store.getterWrapper[k];
computed[k] = function() {
return fn(store.state)
}
//为getters定义只读属性
Object.defineProperty(store.getters,k,{
get: () => store._vm[k]
})
})
到此基本实现vuex功能。