關于vuex
就不再贅述,簡單回顧一下:當應用碰到多個組件共享狀態
時,簡單的單向數據流
很容易被破壞:第一,多個視圖依賴于同一狀態;第二,來自不同視圖的行為需要變更同一狀態。若解決前者使用傳參的方式,則不適用于多層嵌套的組件以及兄弟組件;若解決后者使用父子組件直接引用或事件變更和同步狀態的多份拷貝,則不利于代碼維護。
所以,最好的辦法是:把組件的共享狀態抽取出,以一個全局單例模式管理!這也正是vuex
背后的基本思想。
所以,vuex的大致框架如下:
classStore{constructor(){//state//getters//mutations//actions}//commit//dipatch}
接下來,就寫寫看。
vuecreatevue2-vuex//創建vue2項目yarnaddvuex@next--save//安裝vuexyarnserve//啟動項目
1、State
(1)使用
//store.js//倉庫importVuefrom'vue'importVuexfrom'vuex'importextrafrom'./extra.js'Vue.use(Vuex)//引入vuex的方式,說明Store需要install方法exportdefaultnewVuex.Store({//倉庫數據源state:{count:1,dowhat:'addCount'},}
//app.vue<template><pclass="testState"><p>{{mycount}}</p><p>{{dowhat}}:{{count}}</p></p></template><script>exportdefault{import{mapState}from'vuex'//推薦方式computed:mapState()({mycount:state=>state.count}),//推薦方式的簡寫方式computed:{//解構的是getters...mapState(['count','dowhat'])},}</script>
(2)注意
由于 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性
中返回某個狀態,這種模式導致組件依賴全局狀態單例
。在模塊化的構建系統中,在每個需要使用 state 的組件中需要頻繁地導入,并且在測試組件時需要模擬狀態
Vuex 通過 store
選項,提供了一種機制將狀態從根組件“注入”到每一個子組件中(需調用 Vue.use(Vuex)
)
(3)實現
所以除了Store
內部的五大屬性以外,還需要考慮插件的一個install
方法,所以大致框架如下:
classStore{constructor(){//state//getters//mutations//actions//modules}//commit//dipatch}letVuex={Store,Install}exportdefaultVuex
所以,接下來就可以具體實現了,
classStore{constructor(options){//statethis.state=options.state}}letinstall=function(_Vue){_Vue.mixin({beforeCreate(){//在組件創建之前自動調用,每個組件都有這個鉤子if(this.$options&&this.$options.store){//this.$options讀取根組件this.$store=this.$options.store}else{this.$store=this.$parent&&this.$parent.$store}}})}
然而,上述的state的實現有一個缺點:當改變數據的時候,state
的數據不能動態的渲染。所以如何把state
里的數據成為響應式成為關鍵問題?實際上,類似vue
里的data
,也可以通過這種方式讓其成為響應式。那么就得從install
方法中傳入Vue
,所以改變后:
letVue=nullclassStore{constructor(options){//statethis.vm=new_Vue({data:{state:options.state//data中的數據才是響應式}})}getstate(){returnthis.vm.state}}letinstall=function(_Vue){//用于Vue.use(plugin)Vue=_Vue_Vue.mixin({onBeforeCreate(){//在組件創建之前自動調用,每個組件都有這個鉤子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.jsexportdefaultnewVuex.Store({//計算屬性getters:{//這里的函數不需要調用,可以直接使用,官方默認前面有getgetCount(state){//接受state作為其第一個參數returnstate.count*100;}},}
(2)注意
有時候我們需要從 store 中的 state 中派生出一些狀態(比如增加,刪除,過濾等等),Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算,Getter 接受 state 作為其第一個參數,getter 在通過方法訪問時,每次都會去進行調用,而不會緩存結果
(3)實現
//gettersletgetters=options.getters||{}this.getters={}Object.keys(getters).forEach(getterName=>{Object.defineProperty(this.getters,getterName,{get:()=>{returngetters[getterName](this.state)}})})
3、mutations
(1)使用
//store.jsexportdefaultnewVuex.Store({//相當于methodsmutations:{//mutations內部的函數,天生具備一個形參add(state,n){state.count+=n;},decrease(state,n){state.count-=n;}},}
methods:{submit(){console.log('success');},//解構倉庫mutations里面的方法,要啥解構啥...mapMutations(['add','decrease']),//this.$store.commit('add'),...mapActions(['addAction','decreaseAction']),//this.addAction()調用actions里面的方法//this.$store.dispatch('add'),}
(2)注意
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler) 。這個回調函數就是進行狀態更改的地方,并且它會接受 state 作為第一個參數,不能直接調用一個 mutation handler。這個選項更像是事件注冊:“當觸發一個類型為 increment
的 mutation 時,調用此函數?!币獑拘岩粋€ mutation handler,你需要以相應的 type 調用 store.commit 方法
可以向 store.commit
傳入額外的參數,即 mutation 的 載荷(payload) ,在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段并且記錄的 mutation 會更易讀
(3)實現
//mutationsletmutations=options.mutations||{}this.mutations={}Object.keys(mutations).forEach(mutationName=>{this.mutations[mutationName]=(arg)=>{//保證多個(第二個)參數的傳入mutations[mutationName](this.state,arg)}})commit=(method,arg)=>{//使用箭頭函數改變被調用的this的指向//console.log(this);this.mutations[method](arg)}
4、actions
(1)使用
//store.jsexportdefaultnewVuex.Store({actions:{addAction(context){//在這里調用add方法context.commit('add',10);},decreaseAction({commit}){commit('decreaseAction',5)}},}
(2)注意
Action 提交的是 mutation,而不是直接變更狀態。
Action 可以包含任意異步操作
Action 函數接受一個與 store 實例具有相同方法和屬性的 context 對象
Action 通過 store.dispatch
方法觸發
Action 通常是異步的,store.dispatch
可以處理被觸發的 action 的處理函數返回的 Promise,并且 store.dispatch
仍舊返回 Promise
一個 store.dispatch
在不同模塊中可以觸發多個 action 函數。在這種情況下,只有當所有觸發函數完成后,返回的 Promise 才會執行
(3)實現
//actionsletactions=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)使用
//actionsletactions=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.jsmodules:{extra:extra}
(2)注意
由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫,Vuex 允許我們將 store 分割成模塊(module) 。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割
對于模塊內部的 mutation 和 getter,接收的第一個參數是模塊的局部狀態對象
對于模塊內部的 action,局部狀態通過 context.state
暴露出來,根節點狀態則為 context.rootState
對于模塊內部的 getter,根節點狀態(rootState)會作為第三個參數暴露出來
letVue=null//全局的_VueclassStore{constructor(options){//state//this.state=options.state寫法不完美,當改變數據的時候,不能動態的渲染,所以需要把data中的數據做成響應式的this.vm=new_Vue({data:{state:options.state//data中的數據才是響應式}})//gettersletgetters=options.getters||{}this.getters={}Object.keys(getters).forEach(getterName=>{Object.defineProperty(this.getters,getterName,{get:()=>{returngetters[getterName](this.state)}})})//mutationsletmutations=options.mutations||{}this.mutations={}Object.keys(mutations).forEach(mutationName=>{this.mutations[mutationName]=(arg)=>{//保證多個(第二個)參數的傳入mutations[mutationName](this.state,arg)}})//actionsletactions=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)}getstate(){returnthis.vm.state}}letinstall=function(_Vue){Vue=_VueVue.mixin({beforeCreate(){//在組件創建之前自動調用,每個組件都有這個鉤子if(this.$options&&this.$options.store){//this.$options讀取到根組件this.$store=this.$options.store}else{////如果不是根組件的話,也把$store掛到上面,因為是樹狀組件this.$store=this.$parent&&this.$parent.$store}}})}letVuex={Store,install}exportdefaultVuex
到此,相信大家對“vuex的實現原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是本站網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
姓名:秦繼偉出生日期:1914年11月16日。死亡日期:1997年2月2日入黨日期:1930年4月民族:漢族。出生地:湖北黃安縣七里坪區羅欽莊家庭構成:富農家庭妻子:唐先梅排名:中將(1955年)海軍上將(1988年)軍銜:正規軍銜。獎章:二級八一獎章。一級獨立自由勛章一級解放勛章(編號:02358)1923年在七里坪區私立學校讀書927.11參加黃麻起義1928.12參加壯族紅衛兵1929.8中...
作為一種在國外資本市場上運用成熟的估值調整方法,“對賭協議”在我國仍然屬于一種新興事物。對賭協議是什么意思?對賭協議是期權的一種形式,即投資方和融資方達成融資并購協議后,對未來不確定事項進行一種事先約定,一旦將來真發生了約定的情形時,融資方可行使一種權利; 如果將來未發生約定的情形,那投資方可行使一種權利。對賭協議帶有一定的風險性, 很多企業為了盡快獲得融資,就不得不簽訂這...
(資料圖片)在生活中,很多人都不知道如何刪除小哨兵還原卡是什么意思,其實他的意思是非常簡單的,下面就是小編搜索到的如何刪除小哨兵還原卡相關的一些知識,我們一起來學習下吧!初次安裝小哨兵還原卡: 1、 準備好相對應的小哨兵還原卡的驅動程序;2、 開機進入Windows界面,安裝小哨兵還原卡的驅動,安裝完畢后重啟。3、 關機。4、 打開電腦側板,將小哨兵還原卡插在電腦主板的PCI槽或網槽上。5、 開機...