本篇內(nèi)容主要講解“vuex的實(shí)現(xiàn)原理是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“vuex的實(shí)現(xiàn)原理是什么”吧!
目前創(chuàng)新互聯(lián)公司已為上1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、永安網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
關(guān)于vuex
就不再贅述,簡(jiǎn)單回顧一下:當(dāng)應(yīng)用碰到多個(gè)組件共享狀態(tài)
時(shí),簡(jiǎn)單的單向數(shù)據(jù)流
很容易被破壞:第一,多個(gè)視圖依賴(lài)于同一狀態(tài);第二,來(lái)自不同視圖的行為需要變更同一狀態(tài)。若解決前者使用傳參的方式,則不適用于多層嵌套的組件以及兄弟組件;若解決后者使用父子組件直接引用或事件變更和同步狀態(tài)的多份拷貝,則不利于代碼維護(hù)。
所以,最好的辦法是:把組件的共享狀態(tài)抽取出,以一個(gè)全局單例模式管理!這也正是vuex
背后的基本思想。
所以,vuex的大致框架如下:
class Store {
constructor() {
// state
// getters
// mutations
// actions
}
// commit
// dipatch
}
接下來(lái),就寫(xiě)寫(xiě)看。
vue create vue2-vuex//創(chuàng)建vue2項(xiàng)目
yarn add vuex@next --save//安裝vuex
yarn serve//啟動(dòng)項(xiàng)目
1、State
(1)使用
//store.js
// 倉(cāng)庫(kù)
import Vue from 'vue'
import Vuex from 'vuex'
import extra from './extra.js'
Vue.use(Vuex) //引入vuex的方式,說(shuō)明Store需要install方法
export default new Vuex.Store({
// 倉(cāng)庫(kù)數(shù)據(jù)源
state: {
count: 1,
dowhat: 'addCount'
},
}
//app.vue
<template>
<div class="testState">
<p>{{mycount}}</p>
<p>{{dowhat}}:{{count}}</p>
</div>
</template>
<script>
export default {
import {
mapState
} from 'vuex'
// 推薦方式
computed: mapState()({
mycount: state => state.count
}),
// 推薦方式的簡(jiǎn)寫(xiě)方式
computed: {
// 解構(gòu)的是getters
...mapState(['count', 'dowhat'])
},
}
</script>
(2)注意
由于 Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的,從 store 實(shí)例中讀取狀態(tài)最簡(jiǎn)單的方法就是在計(jì)算屬性
中返回某個(gè)狀態(tài),這種模式導(dǎo)致組件依賴(lài)全局狀態(tài)單例
。在模塊化的構(gòu)建系統(tǒng)中,在每個(gè)需要使用 state 的組件中需要頻繁地導(dǎo)入,并且在測(cè)試組件時(shí)需要模擬狀態(tài)
Vuex 通過(guò) store
選項(xiàng),提供了一種機(jī)制將狀態(tài)從根組件“注入”到每一個(gè)子組件中(需調(diào)用 Vue.use(Vuex)
)
(3)實(shí)現(xiàn)
所以除了Store
內(nèi)部的五大屬性以外,還需要考慮插件的一個(gè)install
方法,所以大致框架如下:
class Store {
constructor() {
// state
// getters
// mutations
// actions
//modules
}
// commit
// dipatch
}
let Vuex = {
Store,
Install
}
export default Vuex
所以,接下來(lái)就可以具體實(shí)現(xiàn)了,
class Store {
constructor(options) {
// state
this.state = options.state
}
}
let install = function(_Vue) {
_Vue.mixin({
beforeCreate() { //在組件創(chuàng)建之前自動(dòng)調(diào)用,每個(gè)組件都有這個(gè)鉤子
if (this.$options && this.$options.store) { //this.$options讀取根組件
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
然而,上述的state的實(shí)現(xiàn)有一個(gè)缺點(diǎn):當(dāng)改變數(shù)據(jù)的時(shí)候,state
的數(shù)據(jù)不能動(dòng)態(tài)的渲染。所以如何把state
里的數(shù)據(jù)成為響應(yīng)式成為關(guān)鍵問(wèn)題?實(shí)際上,類(lèi)似vue
里的data
,也可以通過(guò)這種方式讓其成為響應(yīng)式。那么就得從install
方法中傳入Vue
,所以改變后:
let Vue=null
class Store {
constructor(options) {
// state
this.vm = new _Vue({
data: {
state: options.state//data中的數(shù)據(jù)才是響應(yīng)式
}
})
}
get state() {
return this.vm.state
}
}
let install = function(_Vue) {//用于Vue.use(plugin)
Vue=_Vue
_Vue.mixin({
onBeforeCreate() { //在組件創(chuàng)建之前自動(dòng)調(diào)用,每個(gè)組件都有這個(gè)鉤子
if (this.$options && this.$options.store) { //this.$options讀取根組件
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
2、getters
(1)使用
//store.js
export default new Vuex.Store({
// 計(jì)算屬性
getters: {
// 這里的函數(shù)不需要調(diào)用,可以直接使用,官方默認(rèn)前面有g(shù)et
getCount(state) {//接受 state 作為其第一個(gè)參數(shù)
return state.count * 100;
}
},
}
(2)注意
有時(shí)候我們需要從 store 中的 state 中派生出一些狀態(tài)(比如增加,刪除,過(guò)濾等等),Vuex 允許我們?cè)?store 中定義“getter”(可以認(rèn)為是 store 的計(jì)算屬性)。就像計(jì)算屬性一樣,getter 的返回值會(huì)根據(jù)它的依賴(lài)被緩存起來(lái),且只有當(dāng)它的依賴(lài)值發(fā)生了改變才會(huì)被重新計(jì)算,Getter 接受 state 作為其第一個(gè)參數(shù),getter 在通過(guò)方法訪問(wèn)時(shí),每次都會(huì)去進(jìn)行調(diào)用,而不會(huì)緩存結(jié)果
(3)實(shí)現(xiàn)
// getters
let getters = options.getters || {}
this.getters = {}
Object.keys(getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {
get: () => {
return getters[getterName](this.state)
}
})
})
3、mutations
(1)使用
//store.js
export default new Vuex.Store({
// 相當(dāng)于methods
mutations: {
// mutations內(nèi)部的函數(shù),天生具備一個(gè)形參
add(state, n) {
state.count += n;
},
decrease(state, n) {
state.count -= n;
}
},
}
methods: {
submit() {
console.log('success');
},
// 解構(gòu)倉(cāng)庫(kù)mutations里面的方法,要啥解構(gòu)啥
...mapMutations(['add', 'decrease']),
// this.$store.commit('add'),
...mapActions(['addAction', 'decreaseAction']),
// this.addAction()調(diào)用actions里面的方法
// this.$store.dispatch('add'),
}
(2)注意
更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 類(lèi)似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類(lèi)型 (type)和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù),不能直接調(diào)用一個(gè) mutation handler。這個(gè)選項(xiàng)更像是事件注冊(cè):“當(dāng)觸發(fā)一個(gè)類(lèi)型為 increment
的 mutation 時(shí),調(diào)用此函數(shù)。”要喚醒一個(gè) mutation handler,你需要以相應(yīng)的 type 調(diào)用 store.commit方法
可以向 store.commit
傳入額外的參數(shù),即 mutation 的 載荷(payload),在大多數(shù)情況下,載荷應(yīng)該是一個(gè)對(duì)象,這樣可以包含多個(gè)字段并且記錄的 mutation 會(huì)更易讀
(3)實(shí)現(xiàn)
// mutations
let mutations = options.mutations || {}
this.mutations = {}
Object.keys(mutations).forEach(mutationName => {
this.mutations[mutationName] = (arg) => {//保證多個(gè)(第二個(gè))參數(shù)的傳入
mutations[mutationName](this.state, arg)
}
})
commit = (method, arg) => {//使用箭頭函數(shù)改變被調(diào)用的this的指向
// console.log(this);
this.mutations[method](arg)
}
4、actions
(1)使用
//store.js
export default new Vuex.Store({
actions: {
addAction(context) {
// 在這里調(diào)用add方法
context.commit('add', 10);
},
decreaseAction({
commit
}) {
commit('decreaseAction', 5)
}
},
}
(2)注意
Action 提交的是 mutation,而不是直接變更狀態(tài)。
Action 可以包含任意異步操作
Action 函數(shù)接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象
Action 通過(guò) store.dispatch
方法觸發(fā)
Action 通常是異步的,store.dispatch
可以處理被觸發(fā)的 action 的處理函數(shù)返回的 Promise,并且 store.dispatch
仍舊返回 Promise
一個(gè) store.dispatch
在不同模塊中可以觸發(fā)多個(gè) action 函數(shù)。在這種情況下,只有當(dāng)所有觸發(fā)函數(shù)完成后,返回的 Promise 才會(huì)執(zhí)行
(3)實(shí)現(xiàn)
// actions
let actions = options.actions || {}
this.actions = {}
Object.keys(actions).forEach(actionName => {
this.actions[actionName] = (arg) => {
actions[actionName](this, arg)
}
})
dispatch=(method, arg) =>{
this.actions[method](arg)
}
5、modules
(1)使用
// actions
let actions = options.actions || {}
this.actions = {}
Object.keys(actions).forEach(actionName => {
this.actions[actionName] = (arg) => {
actions[actionName](this, arg)
}
})
dispatch=(method, arg) =>{
this.actions[method](arg)
}
//store.js
modules: {
extra: extra
}
(2)注意
由于使用單一狀態(tài)樹(shù),應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就有可能變得相當(dāng)臃腫,Vuex 允許我們將 store 分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割
對(duì)于模塊內(nèi)部的 mutation 和 getter,接收的第一個(gè)參數(shù)是模塊的局部狀態(tài)對(duì)象
對(duì)于模塊內(nèi)部的 action,局部狀態(tài)通過(guò) context.state
暴露出來(lái),根節(jié)點(diǎn)狀態(tài)則為 context.rootState
對(duì)于模塊內(nèi)部的 getter,根節(jié)點(diǎn)狀態(tài)(rootState)會(huì)作為第三個(gè)參數(shù)暴露出來(lái)
let Vue = null//全局的_Vue
class Store {
constructor (options) {
// state
//this.state = options.state 寫(xiě)法不完美,當(dāng)改變數(shù)據(jù)的時(shí)候,不能動(dòng)態(tài)的渲染,所以需要把data中的數(shù)據(jù)做成響應(yīng)式的
this.vm = new _Vue({
data: {
state: options.state//data中的數(shù)據(jù)才是響應(yīng)式
}
})
// getters
let getters = options.getters || {}
this.getters = {}
Object.keys(getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {
get: () => {
return getters[getterName](this.state)
}
})
})
// mutations
let mutations = options.mutations || {}
this.mutations = {}
Object.keys(mutations).forEach(mutationName => {
this.mutations[mutationName] = (arg) => {//保證多個(gè)(第二個(gè))參數(shù)的傳入
mutations[mutationName](this.state, arg)
}
})
// actions
let actions = options.actions || {}
this.actions = {}
Object.keys(actions).forEach(actionName => {
this.actions[actionName] = (arg) => {
actions[actionName](this, arg)
}
})
}
dispatch=(method, arg) =>{
this.actions[method](arg)
}
commit = (method, arg) => {
// console.log(this);
this.mutations[method](arg)
}
get state() {
return this.vm.state
}
}
let install = function(_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate() {//在組件創(chuàng)建之前自動(dòng)調(diào)用,每個(gè)組件都有這個(gè)鉤子
if (this.$options && this.$options.store) { // this.$options讀取到根組件
this.$store = this.$options.store
} else { // //如果不是根組件的話,也把$store掛到上面,因?yàn)槭菢?shù)狀組件
this.$store = this.$parent && this.$parent.$store
}
}
})
}
let Vuex = {
Store,
install
}
export default Vuex
到此,相信大家對(duì)“vuex的實(shí)現(xiàn)原理是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
本文題目:vuex的實(shí)現(xiàn)原理是什么
當(dāng)前URL:http://chinadenli.net/article2/ihohic.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站導(dǎo)航、企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計(jì)公司、網(wǎng)站收錄、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)