前言
vuex是一种专为Vue.js应用程序开发的状态管理模式,挂载在全局中,具有响应式特性
vuex的实现原理主要包括以下几个方面:
- 是一个对象,vuex有两个属性,一个是Store类,一个是install方法。
- Store类:用来创建store实例的,它接收一个对象作为参数,包含state, getters, mutations, actions等属性。
- install方法:用来将store实例注入到每个Vue组件中的,它利用了Vue的mixin机制,在beforeCreate钩子中执行vuexInit方法,将store实例挂载到每个组件的$store属性上。
- state:利用Vue的响应式data实现的,它将用户传入的state对象作为new Vue的data选项,从而实现了state的数据响应。
- getters:利用Vue的计算属性computed实现的,它将用户传入的getters对象作为new Vue的computed选项,从而实现了getters的缓存和依赖追踪。
- vuex的mutations是用来同步修改state的方法,它只能接收两个参数,一个是state,一个是payload,它必须是同步函数,不能包含异步操作。
- actions:用来异步修改state的方法,它可以接收一个context对象作为参数,包含state, getters, commit, dispatch等属性,它可以包含异步操作,但最终还是要通过commit调用mutations来修改state。
- vuex还提供了一些辅助函数,如mapState, mapGetters, mapMutations, mapActions等,用于简化组件中的store访问和操作。
下面是一个简单的代码示例,用于说明vuex的实现原理:文章来源:https://www.toymoban.com/news/detail-770370.html
// vuex.js
let Vue // 保存Vue构造函数,插件中要使用
class Store {
constructor(options) {
// 保存选项
this.$options = options
// 定义响应式的state
this._vm = new Vue({
data: {
$$state: options.state // 加两个$,Vue不做代理
},
computed: options.getters // 将getters定义为计算属性
})
// 定义commit和dispatch方法
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
// 定义wrappedGetters
this.wrappedGetters = {}
// 实现getters,按照getters的定义挂载到store实例
const computed = {}
Object.keys(this.$options.getters).forEach(key => {
// 获取用户定义的getter
const fn = this.$options.getters[key]
// 转换为computed可以使用无参数形式
computed[key] = () => {
return fn(this.state, this.getters)
}
// 为wrappedGetters定义只读属性
Object.defineProperty(this.wrappedGetters, key, {
get: () => this._vm[key]
})
})
// 实现mutations
this.mutations = {}
Object.keys(this.$options.mutations).forEach(key => {
this.mutations[key] = payload => {
this.$options.mutationskey
}
})
// 实现actions
this.actions = {}
Object.keys(this.$options.actions).forEach(key => {
this.actions[key] = payload => {
this.$options.actionskey
}
})
}
// 存取器,state只读
get state() {
return this._vm._data.$$state
}
set state(v) {
console.error('不能直接修改state,请使用replaceState')
}
// 存取器,getters只读
get getters() {
return this.wrappedGetters
}
// commit,执行mutation
commit(type, payload) {
// 获取type对应的mutation
const fn = this.mutations[type]
if (!fn) {
// 未定义的mutation
console.error(`mutation ${type} 不存在`)
return
}
// 传入state和负载
fn(payload)
}
// dispatch,执行action
dispatch(type, payload) {
// 获取type对应的action
const fn = this.actions[type]
if (!fn) {
// 未定义的action
console.error(`action ${type} 不存在`)
return
}
// 传入当前Store实例和负载
return fn(payload)
}
}
// install方法
function install(_Vue) {
Vue = _Vue // 保存Vue构造函数
// 混入
Vue.mixin({
beforeCreate() {
// 此时,上下文已经是组件实例了
// 如果this是根实例,则它的$options里面会有store实例
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
// 以后就能在组件中拿到 $store
}
}
})
}
// 导出对象
export default { Store, install }
然后在app.js文件中引入使用文章来源地址https://www.toymoban.com/news/detail-770370.html
// 引入Vue和Vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 使用Vuex插件
Vue.use(Vuex)
// 创建一个store实例
const store = new Vuex.Store({
// 定义state
state: {
count: 0
},
// 定义getters
getters: {
doubleCount: state => state.count * 2
},
// 定义mutations
mutations: {
increment(state, payload) {
state.count += payload
}
},
// 定义actions
actions: {
incrementAsync(context, payload) {
setTimeout(() => {
context.commit('increment', payload)
}, 1000)
}
}
})
// 在组件中使用store
new Vue({
el: '#app',
store,
...
})
到了这里,关于手写一个vuex?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!