閑話Vuex

      網友投稿 775 2025-04-02

      前言:為什么要Vuex

      在Vue項目中, 功能組件和服務組件的封裝都會有各種各樣的數據傳遞,用 props 定義字段或者是子組件 emit 來通信。但是,當我們的項目的復雜度逐漸增長的時候,組件會越來越多,而且一些組件并不存在調用關系,一些數據需要共享的時候,那么問題就來了:

      傳參的方法對于多層嵌套的組件將會非常繁瑣,并且對于兄弟組件間的狀態傳遞無能為力;

      采用父子組件直接引用或者通過事件來變更和同步狀態的多份拷貝,代碼冗余,慢慢的難以維護。

      所以我們在項目中經常是全局定義一個實例“全局單例模式”,當然你也可以定義多個實例來共享一個數據源。

      比如說我們有一個系統,包含左側菜單組件以及右側內容區域組件兩部分。現在需要在內容區域給系統做一個全屏的功能,即點擊右側按鈕時菜單隱藏。如果我們不使用Vuex,首先我們要在內容組件中使用 $emit 改變父組件的內容,然后將改變后的值傳遞左側菜單組件控制隱藏。而現在我們有了 Vuex,菜單組件和內容組件共享某個狀態變量,需要隱藏時只需要在內容組件中改變狀態,即可在菜單組件中共享到相應的變量。

      Vuex 就是為了解決這些問題而生。

      Vue核心

      state:驅動應用的數據源,類似于?vue?中的?data,是一棵單一狀態樹,涉及到的狀態變量都存放在?state?上。

      getter:store?的計算屬性。類似于?vue?中的?computed?計算屬性。當有多個組件對某個狀態引用后過濾時,需要在多個組件內部使用?computed?進行計算,但有了?Getter?后我們可以將這個計算提前到?Vuex?中,一次計算多處使用。例如下面的代碼我們要過濾出啟用(狀態為?1)狀態的數據:

      mutation:類似于?vue?中的方法,當我們需要改變?Vuex?中的某個變量時需要用到。

      例如我們前面提到的顯示隱藏菜單:

      一般?mutations?中方法接受的第一個參數為?state,后面的參數則是傳遞的值。例如我們需要顯示菜單則在組件中調用:

      this.$store.commit('onCollapse',?true);

      這里改變值需要通過?commit(‘方法名’,?’…參數’)調用。

      Action:? 類似于?mutation,但是改變狀態時只能通過提交?mutation,而不能直接改變。同時?action?可以包含異步的操作,?而?mutation?是不允許包含異步操作的。

      Vuex 模塊分割

      由于 state 使用的是單一狀態樹,在項目較大時會導致 Vuex 變得臃腫且不易維護,這時候我們需要對項目進行分模塊化處理,每一個模塊都有自己的 state、mutation、action、getter:

      Modules

      - app.js

      - user.js

      index.js

      最后統一在?inde.js?中導出:

      import?Vue?from?'vue'

      import?vuex?from?'vuex'

      Vue.use(vuex);

      import?app?from?'./modules/app'

      import?user?from?'./modules/user'

      const?store?=?new?vuex.Store({

      modules:?{

      app:?app,

      user:?user

      }

      })

      export?default?store

      Vuex 輔助函數

      當我們的項目調用比較簡單時輔助函數可能不會起到很大的作用,但當項目調用復雜時,這些輔助函數(mapState、mapGetters、mapMutations、mapActions)能大大提高開發效率,使得代碼更加簡潔優雅。

      其中?mapState、mapGetters?是對變量的獲取,放在組件的?computed?計算屬性中即可,如下:

      computed:?{

      ...mapState({

      themeColor:?state?=>?state.app.themeColor,

      sysName:?state?=>?state.app.appName,

      appHomeRouter:?state?=>?state.app.appHomeRouter,

      })

      閑話Vuex

      }

      而?mapMutations、mapActions?是對方法的調用,需要放在組件的?method?中,如下:

      methods:?{

      ...mapMutations({

      changeStatus:?'changeStatus'

      }),

      changeStatus(){

      this.changeStatus()//直接調用?mapMutations?中的方法

      //?this.$store.commit('changeStatus')//不使用輔助函數時的調用

      },

      ...mapActions({

      numAdd:?'actionNumAdd'

      }),

      actionnum6(){

      this.numAdd()//直接調用?mapActions?中的方法

      //?this.$store.dispatch('actionNumAdd')//不使用輔助函數時的調用

      },

      }

      情景案例

      有時候我們終于完成了一份試卷,可能由于手滑不小心把瀏覽器給關閉或者刷新了一下,導致辛辛苦苦做完的題目又得重頭來過,而?Vuex?結合?Map?同樣可以解決這個問題,核心思想就是將已經做過的題目更新到?Vuex?中。

      講到這里肯定會有人存在疑問:Vuex?中存儲的狀態變量在瀏覽器關閉或者刷新時會重新初始,這樣如何能在瀏覽器刷新的時候獲取到存儲的值呢?這里我們需要引進緩存——sessionStorage。

      首先在?state?中定義一個?answerMap:

      state:?{

      answerMap:?sessionStorage.getItem("answerMap")

      }

      然后在每次做題完成后將答案存儲到?sessionStorage?中,即:

      const?mutations?=?{

      setAnswerMap(state,?answer)?{

      let?map?=?JSON.parse(state.answerMap);

      if?(map?==?null?||?!(map?instanceof?Map))?{

      map?=?new?Map();

      }

      map.set(answer.id,?answer);

      sessionStorage.setItem("answerMap",?JSON.stringify(map))

      },

      }

      正常情況下到這里就結束了,但是實際操作后會發現每次獲取到的?answerMap?總是為?null,原因在于最后一行代碼:

      sessionStorage.setItem("answerMap",?JSON.stringify(map))

      不能直接將?map?通過?JSON.stringify()?進行轉換,需要先將?map?轉成?obj?對象后再轉成?json?對象,將?map?轉成?obj:

      let?obj?=?Object.create(null);

      for?(let?[k,?v]?of?map)?{

      obj[k]?=?v;

      }

      此時在獲取則解決為?null?的情況,完善后代碼如下:

      const?mutations?=?{

      setAnswerMap(state,?answer)?{

      let?map?=?JSON.parse(state.answerMap);

      if?(map?==?null?||?!(map?instanceof?Map))?{

      map?=?new?Map();

      }

      map.set(answer.id,?answer);

      let?obj?=?Object.create(null);

      for?(let?[k,?v]?of?map)?{

      obj[k]?=?v;

      }

      sessionStorage.setItem("answerMap",?JSON.stringify(obj))

      },

      }

      這里借助了?Vuex?+?map?+?sessionStorage?防止已做題目丟失的情況,當然只是提供一種解決問題的思路,可能在真實場景中會更加復雜,需要根據不同的場景靈活運用。比如說我們如果需要在手動清除瀏覽器緩存、甚至服務器奔潰后依舊能獲取到已做的題目則使用?Vuex?明顯不合適,此時就需要利用?Redis?緩存來處理。

      在實際項目中可能會遇到更加復雜的情況,但是萬變不離其宗,在掌握基礎的情況下總會有一種思路能夠更好的解決問題。

      Vue 數據結構

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:EXCEL中一個簡單又不簡單的單元格有哪些秘密(excel單元格中有個更小的格子)
      下一篇:WPS2019政府版專業增強版純凈無廣告下載(去除政府版logo、WPS網盤)
      相關文章
      亚洲偷自拍另类图片二区| 亚洲w码欧洲s码免费| 亚洲天然素人无码专区| 亚洲免费在线视频观看| 亚洲日本香蕉视频观看视频| 亚洲综合激情视频| 亚洲精品免费在线| 亚洲午夜电影在线观看高清 | 国产成人精品久久亚洲高清不卡 | 亚洲AV无码一区二区三区网址| 亚洲人成人伊人成综合网无码| 亚洲精品无码久久久久A片苍井空 亚洲精品无码久久久久YW | 亚洲综合精品一二三区在线| 老汉色老汉首页a亚洲| 亚洲美女视频一区二区三区| 久久亚洲精品人成综合网| 亚洲综合激情九月婷婷| 亚洲国产成人久久| 亚洲综合久久精品无码色欲| 亚洲色少妇熟女11p| 国产精品亚洲综合一区在线观看| 午夜亚洲福利在线老司机| 亚洲国产成人久久精品99| 亚洲日韩欧洲乱码AV夜夜摸| 亚洲成AV人在线播放无码| 久久久久亚洲AV成人片| 亚洲国产品综合人成综合网站| 97se亚洲国产综合自在线| 久久亚洲色WWW成人欧美| 亚洲国产精品一区二区第一页免| 国产亚洲美日韩AV中文字幕无码成人| 国外亚洲成AV人片在线观看| 亚洲AV无码专区电影在线观看 | 亚洲最大福利视频网站| 亚洲1区1区3区4区产品乱码芒果| 中日韩亚洲人成无码网站| 国产精品久久久久久亚洲小说| 亚洲一级片免费看| 久久精品亚洲中文字幕无码网站| 亚洲精品视频免费在线观看| 亚洲天然素人无码专区|