正文
准备开始
我们将采用 TDD 的方式完成本次开发。需要安装的只有两样:
vue
和
jest
。 通过
yarn add [email protected] babel-jest @babel/core @babel/preset-env
安装它们。需要做一些基础的配置 - 按其文档配置即可。
反应式状态
第一个测试是关于
state
的:
test('reactive state', () => {
const store = new Vuex.Store({
state: {
count: 0
}
})
expect(store.state).toEqual({ count: 0 })
store.state.count++
expect(store.state).toEqual({ count: 1 })
})
复制代码
毫无悬念地失败了 — Vuex 为 undefined。让我们定义它:
class Store {
}
const Vuex = {
Store
}
复制代码
现在我们得到的是
Expected: {"count": 0}, Received: undefined
。让我们从
vue
中提取
reactive
并让测试通过吧!
import { reactive } from 'vue'
class Store {
constructor(options) {
this.state = reactive(options.state)
}
}
复制代码
Vue 的
reactive
函数真是 so easy。我们在测试中直接修改了
store.state
- 这不太理想,所以来添加一个 mutation 作为替代。
实现 mutations 和 commit
像上面一样,还是先来编写测试:
test('commits a mutation', () => {
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
INCREMENT(state, payload) {
state.count += payload
}
}
})
store.commit('INCREMENT', 1)
expect(store.state).toEqual({ count: 1 })
})
复制代码
测试失败,理所当然。报错信息为
TypeError: store.commit is not a function
。让我们来实现
commit
方法,同时也要把
options.mutations
赋值给
this.mutations
,这样才能在
commit
中访问到:
class Store {
constructor(options) {
this.state = reactive(options.state)
this.mutations = options.mutations
}
commit(handle, payload) {
const mutation = this.mutations[handle]
if (!mutation) {
throw Error(`[Hackex]: ${handle} is not defined`)
}
mutation(this.state, payload)
}
}
复制代码
因为
mutations
只是一个将函数映射为其属性的对象,所以我们用
handle
参数就能取出对应的函数,并传入
this.state
调用它。我们也能为 mutation 未被定义的情况编写一个测试:
test('throws an error for a missing mutation'