深入Vue底层,手写一个vuex
深入底层,手把手教你写一个Vuex1. Vuex是什么?什么场景下使用?2. Vuex的基本使用3. 手写一个vuex1. Vuex是什么?什么场景下使用?Vuex是vue的一个插件,叫做状态管理模式,全局共享某一些状态通俗来讲,当各组件需要共享某一组状态的时候,会用到Vuex,兄弟组件及跨级组件传值也可以派上用场(如果数据量不大,或者组件状态不需要共享也可以用中央信息插件event-bus)2.
·
深入底层,手把手教你写一个Vuex
1. Vuex是什么?什么场景下使用?
- Vuex是vue的一个插件,叫做状态管理模式,全局共享某一些状态
- 通俗来讲,当各组件需要共享某一组状态的时候,会用到Vuex,兄弟组件及跨级组件传值也可以派上用场(如果数据量不大,或者组件状态不需要共享也可以用中央信息插件event-bus)
2. Vuex的基本使用
- vue-cli 4.0 以上,在搭建脚手架的时候选择此项就可以
- 项目搭建完成,便会在src文件夹下看到一个store,这就是自动生成的仓库
- 以下是vuex的一些基本操作,供参考:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name: 'Vuex',
age: 18
},
// 可以看做vuex的计算属性
getters: {
addName(state) {
return `${state.name}牛逼`
}
},
// 提交数据更改
mutations: {
syncAdd(state, payload){
state.age += payload
},
syncReduce(state, payload){
state.age -= payload
}
},
// 处理异步,此处为异步提交数据
actions: {
asyncReduce({commit}, payload) {
setTimeout( () => {
commit('syncReduce', payload)
}, 1000)
}
},
// 管理多个模块,当vuex比较大的时候会用到
modules: {
}
})
- vue组件中的调用
<template>
<div id="app">
<h2>{{$store.state.name}}</h2>
<div>{{$store.getters.addName}}</div>
<div>年龄: {{$store.state.age}}</div>
<div><button @click="add()">加10</button></div>
<div><button @click="reduce()">减10-异步</button></div>
</div>
</template>
<script>
export default {
mounted () {
// 这里可以访问到 vuex中的整个store
console.log(this.$store)
},
methods: {
// 同步加10
add(){
this.$store.commit('syncAdd', 10)
},
// 异步减2
reduce() {
// 会去找对应的action
this.$store.dispatch('asyncReduce', 2)
}
}
}
</script>
3. 手写一个vuex
- 从以上的应用,便可以反推出Vuex的基本源码
let Vue;
class Store {
constructor(options = {}) {
// 实现响应式 核心(刚刚直接拿过用户的数组放上去,是没有响应式的)
this.s = new Vue({
data() {
return { state: options.state }
}
})
// 将用户传入的getters放到store实例之上
let getters = options.getters
this.getters = {}
// 通过循环,拿出键值,绑定访问器属性get 劫持对象的所有属性
Object.keys(getters).forEach((getterName) => {
Object.defineProperty(this.getters,
getterName, {
get: () => {
// 执行此函数
return getters[getterName](this.state)
}
})
})
// 获取所有同步更新的操作方法
let mutations = options.mutations
// 放到实例上去
this.mutations = {}
// 订阅,下面commit是发布
Object.keys(mutations).forEach( (mutationName)=> {
// 当前实例上,通过名找方法
this.mutations[mutationName] = (payload) =>{
// 内部的第一参数是状态
mutations[mutationName](this.state, payload)
}
})
let actions = options.actions
this.actions = {}
forEachFn(actions, (actionName, fn) => {
this.actions[actionName] = (payload) => {
// fn 是这个玩意 asyncReduce
fn(this, payload)
}
})
}
// 提交更改,在当前store找到对应函数执行,通过名字找 发布
commit = (mutationName, payload) => {
this.mutations[mutationName](payload)
}
// action 分发的方法
dispatch = (actionName, payload) => {
this.actions[actionName](payload)
}
// 为了方便取值
get state() {
return this.s.state
}
}
const install = (_Vue) => {
Vue = _Vue
Vue.mixin({
beforeCreate() {
console.log('beforeCreate')
if (this.$options && this.$options.store) { // 根实例
// 根实例增加$store属性
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
install,
Store
}
- 总体思路就是在Vue实例上挂上一个store实例,使用Vue提供的install方法注入,之后将用户传入的都绑定上去即可
1. 希望本文能对大家有所帮助,如有错误,敬请指出
2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!后续将继续奉献优质好文
4. 如果存在疑问,可以私信我(主页有Q)
更多推荐
已为社区贡献12条内容
所有评论(0)