前端工程化之 手撕源码 —— vueX
前端工程化作为我们前端开发的演变趋势,其重要性也日益在我们的日常中体现,例如准备面试的人最经常看到的“源码解读”,今天我们就来模仿Vuex从0打造一款路由插件!在看文章的同时也要注意代码截图,大多数分析写在代码注释中!接下来上教程↓
首先老规矩,我们先修改我们的store/index.js中引入的vuex包名,改成我们自己的文件名,如下图
import Vuex from './zbb-vuex'
接下来,我们就一步步来实现我们的 ‘zbb-vuex’ 。相同目录下创建好我们的js文件后。
首先第一步还是一样,先提供一个install方法来全局混入我们的插件
根据官方用法,我们还需要提供一个Store类导出给用户使用我们的插件,如下图导出:
然后就开始打造属于我们的Store !
class Store { }
先来看看我们平时使用vuex时的姿势:
我们在new了store之后传入了一个对象,并且对象里面提供了我们的vuex特有方法,而且是以键值对的形式传入的。
class Store {
constructor(options) {
this._mutations = options.mutations;
this._actions = options.actions
// 相应化处理state
this.state = new Vue({
data: options.state
})
}
// commit用例 store.commit('add',1)
// type:指定mutation payload:载荷(参数)
commit(type,payload) {
const entry = this._mutations[type] // 根据传进来的type去匹配对应的mutation
if(entry) { // 如果存在就执行
entry(this.state, payload) // 吧state传进 还有参数也传进去
}
}
dispatch(type,payload) {
const entry = this._actions[type]
if(entry) {
entry(this, payload) // 将store实例传进去
}
}
}
如上图,我们接收了两个对象,并提供了修改它们的方法。
细心的朋友就会发现,我们这里的异步函数可能使用了箭头函数,那还能直接this.调用它的commit吗?
这里我们进行一步修改this指向,在constructor中:
constructor(options) {
// 绑定commit dispatch的上下文 指向store实例,避免在store里指向window
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
还有一个问题,我们的vuex在严格模式下其实是不允许我们直接对store中state的数据进行直接的修改赋值的
如果我们这样写,它完全任人宰割,我们需要给它套一层铠甲:
// 改进 如下
class Store {
constructor(options) {
this._vm = new Vue({ // 前面加_ 下划线防止用户直接使用
data:{
// 加俩$ 不会被Vue代理
$$state: options.state
}
})
}
// 存取器,store.state
get state() {
return this._vm._data.$$state
}
set state(v) {
console.log('不允许直接修改')
}
}
通过get和sat方法来修改构造函数内部的属性,以达到可控的目的,这才是我们期望的state状态!
至此,我们的zbb-vuex已经实现了基本功能!