實現(xiàn)vuex原理的示例
效果圖如下:

1. 準(zhǔn)備好環(huán)境
使用 vue/cil 初始化項目配置:
npm install -g @vue/cli //全局安裝@vue/cli vue create demo-vue //創(chuàng)建項目
yarn add vuex安裝vuex創(chuàng)建一個store文件夾并使用:

2. 實現(xiàn)目的
stroe/index.js內(nèi)容如下:(我們的目的將引入自寫的vuex實現(xiàn)vuex基礎(chǔ)功能)
import Vue from 'vue'
import Vuex from 'vuex'
// import Vuex from './myvuex' //我們實現(xiàn)的 青銅版vuex
// import Vuex from './myvuexplus' //我們實現(xiàn)的 白銀版vuex
Vue.use(Vuex) //執(zhí)行install方法 將new Vuex.Store掛載到this.$store
export default new Vuex.Store({
state: {
counter: 0,
userData: {
name: '時間',
age: 18
}
},
getters: {
name(state) {
return state.userData.name
}
},
mutations: {
add(state) {
state.counter++
},
updateName(state, payload) {
state.userData.name = payload
}
},
actions: {
add({ commit }) {
setTimeout(() => {
commit('add')
}, 1000);
}
}
})
- 青銅版vuexmyvuex.js代碼如下:
let Vue
class Store {
constructor(options) {
this._vm = new Vue({
data: {
state: options.state
}
})
let getters = options.getters
this.getters = {}
Object.keys(getters).forEach((val) => {
Object.defineProperty(this.getters, val, { //getters響應(yīng)式
get: () => {
return getters[val](this.state)
}
})
})
this._actions = Object.assign({}, options.actions)
this._mutations = Object.assign({}, options.mutations)
}
// get/set state目的:防止外部直接修改state
get state() {
return this._vm.state
}
set state(value) {
console.error('please use replaceState to reset state')
}
commit = (funName, params) => { //this執(zhí)行問題
// 在mutations中找到funName中對應(yīng)的函數(shù)并且執(zhí)行
this._mutations[funName](this.state, params)
}
dispatch(funName, params) {
this._actions[funName](this, params)
}
}
function install(vue) {
Vue = vue
vue.mixin({
beforeCreate () {
// 將 new Store() 實例掛載到唯一的根組件 this 上
if (this.$options?.store) {
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default {
Store,
install
}
青銅版vuex this.$stroe:

- 白銀版vuexmyvuexplus.js代碼如下:
let _Vue
const install = function(Vue, opts) {
_Vue = Vue
_Vue.mixin({ // 因為我們每個組件都有 this.$store這個東西,所以我們使用混入模式
beforeCreate () { // 從根組件向子組件遍歷賦值,這邊的 this 就是每個 Vue 實例
if (this.$options && this.$options.store) { // 這是根節(jié)點(diǎn)
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
class ModuleCollection {
constructor(opts) {
this.root = this.register(opts)
}
register(module) {
let newModule = {
_raw: module,
_state: module.state || {},
_children: {}
}
Object.keys(module.modules || {}).forEach(moduleName => {
newModule._children[moduleName] = this.register(module.modules[moduleName])
})
return newModule
}
}
class Store {
constructor(opts) {
this.vm = new _Vue({
data () {
return {
state: opts.state // 把對象變成響應(yīng)式的,這樣才能更新視圖
}
}
})
this.getters = {}
this.mutations = {}
this.actions = {}
// 先格式化傳進(jìn)來的 modules 數(shù)據(jù)
// 嵌套模塊的 mutation 和 getters 都需要放到 this 中
this.modules = new ModuleCollection(opts)
console.log(this.modules)
Store.installModules(this, [], this.modules.root)
}
commit = (mutationName, value) => { // 這個地方 this 指向會有問題,這其實是掛載在實例上
this.mutations[mutationName].forEach(f => f(value))
}
dispatch(actionName, value) {
this.actions[actionName].forEach(f => f(value))
}
get state() {
return this.vm.state
}
}
Store.installModules = function(store, path, curModule) {
let getters = curModule._raw.getters || {}
let mutations = curModule._raw.mutations || {}
let actions = curModule._raw.actions || {}
let state = curModule._state || {}
// 把子模塊的狀態(tài)掛載到父模塊上,其他直接掛載到根 store 上即可
if (path.length) {
let parent = path.slice(0, -1).reduce((pre, cur) => {
return pre[cur]
}, store.state)
_Vue.set(parent, path[path.length - 1], state)
}
Object.keys(getters).forEach(getterName => {
Object.defineProperty(store.getters, getterName, {
get: () => {
return getters[getterName](state)
}
})
})
Object.keys(mutations).forEach(mutationName => {
if (!(store.mutations && store.mutations[mutationName])) store.mutations[mutationName] = []
store.mutations[mutationName].push(value => {
mutations[mutationName].call(store, state, value)
})
})
Object.keys(actions).forEach(actionName => {
if (!(store.actions && store.actions[actionName])) store.actions[actionName] = []
store.actions[actionName].push(value => {
actions[actionName].call(store, store, value)
})
})
Object.keys(curModule._children || {}).forEach(module => {
Store.installModules(store, path.concat(module), curModule._children[module])
})
}
// computed: mapState(['name'])
// 相當(dāng)于 name(){ return this.$store.state.name }
const mapState = list => { // 因為最后要在 computed 中調(diào)用
let obj = {}
list.forEach(stateName => {
obj[stateName] = () => this.$store.state[stateName]
})
return obj
}
const mapGetters = list => { // 因為最后要在 computed 中調(diào)用
let obj = {}
list.forEach(getterName => {
obj[getterName] = () => this.$store.getters[getterName]
})
return obj
}
const mapMutations = list => {
let obj = {}
list.forEach(mutationName => {
obj[mutationName] = (value) => {
this.$store.commit(mutationName, value)
}
})
return obj
}
const mapActions = list => {
let obj = {}
list.forEach(actionName => {
obj[actionName] = (value) => {
this.$store.dispatch(actionName, value)
}
})
return obj
}
export default {
install,
Store,
mapState,
mapGetters,
mapMutations,
mapActions
}
白銀版vuex this.$stroe:

3. App.vue 內(nèi)使用自寫的vuex:
<template>
<div id="app">
<button @click="$store.commit('add')">$store.commit('add'): {{$store.state.counter}}</button>
<br>
<button @click="$store.commit('updateName', new Date().toLocaleString())">$store.commit('updateName', Date): {{$store.getters.name}}</button>
<br>
<button @click="$store.dispatch('add')">async $store.dispatch('add'): {{$store.state.counter}}</button>
</div>
</template>
<script>
...
以上就是實現(xiàn)vuex原理的示例的詳細(xì)內(nèi)容,更多關(guān)于實現(xiàn)vuex原理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue+element-ui 實現(xiàn)表格的分頁功能示例
這篇文章主要介紹了Vue+element-ui 實現(xiàn)表格的分頁功能示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
Vue實現(xiàn)Header漸隱漸現(xiàn)效果的實例代碼
這篇文章主要介紹了Vue實現(xiàn)Header漸隱漸現(xiàn)效果,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11
Vue如何在CSS中使用data定義的數(shù)據(jù)淺析
這篇文章主要給大家介紹了關(guān)于Vue如何在CSS中使用data定義的數(shù)據(jù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-05-05
vue+ElementUI 關(guān)閉對話框清空驗證,清除form表單的操作
這篇文章主要介紹了vue+ElementUI 關(guān)閉對話框清空驗證,清除form表單的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Vue通過自定義指令實現(xiàn)內(nèi)容替換的示例代碼
這篇文章主要介紹了利用Vue通過自定義指令實現(xiàn)內(nèi)容替換的方法,通過Vue.directive指令定義函數(shù)來實現(xiàn)內(nèi)容自定義,通過指令定義函數(shù)的三個鉤子函數(shù)(inserted、componentUpdated、unbind)來實現(xiàn)自定義內(nèi)容的掛載、更新和銷毀,需要的朋友可以參考下2025-03-03
Element通過v-for循環(huán)渲染的form表單校驗的實現(xiàn)
日常業(yè)務(wù)開發(fā)中,form表單校驗是一個很常見的問題,本文主要介紹了Element通過v-for循環(huán)渲染的form表單校驗的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
vue實現(xiàn)發(fā)送短信倒計時和重發(fā)短信功能的示例詳解
這篇文章主要給大家介紹了vue實現(xiàn)發(fā)送短信倒計時和重發(fā)短信功能的相關(guān)知識,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12

