首頁 >web前端 >js教程 >如何使用vuex實現選單管理

如何使用vuex實現選單管理

亚连
亚连原創
2018-06-19 14:36:001984瀏覽

本篇文章主要介紹了詳解使用vuex進行選單管理,現在分享給大家,也給大家做個參考。

vuex 的優勢在複雜狀態管理中才能提現出來。

如果專案中有多級選單,且不同元件中散佈多個相同等級的選單,專案同一時刻各級選單有且僅有一個高亮,選單跳轉時除了路由改變,對應選單也要高亮(之前的恢復非高亮狀態),這便是個使用vuex 再好不過的場景。

使用DOM 操作進行簡單選單管理

使用DOM 進行選單管理,背後的想法是:在點擊選單的同時,將事件物件傳入事件處理程序,想讓目前高亮的menu 非高亮,再讓點擊的menu 高亮。

<p class="menu-url">
 <span class="active userList" @click="menuClicked($event, &#39;userList&#39;)">注册</span>
 <span class="chargeList" @click="menuClicked($event, &#39;chargeList&#39;)">充值</span>
 <span class="buyList" @click="menuClicked($event, &#39;buyList&#39;)">购买</span>
 <span class="bangList" @click="menuClicked($event, &#39;bangList&#39;)">到期</span>
 <span class="withDrawList" @click="menuClicked($event, &#39;withDrawList&#39;)">提现</span>
</p>
menuClicked (event, url) {
 // 当前高亮的 menu 非高亮
 const currentActiveLink = this.querySelector(&#39;.active&#39;);
 currentActiveLink.classList.remove(&#39;active&#39;);
 // 当前点击的 menu 高亮
 event.target.classList.add(&#39;active&#39;);
 // 路由跳转
 this.$router.push(`/panel/list/${url}`);
},

這樣雖然實現了點擊切換時menu 高亮,但有一個bug:每次初始化都會使預設的menu 變成高亮,如果此時在非預設高亮的menu 中用戶手動刷新頁面,會導致menu 高亮錯誤(例如在buylist 頁面刷新頁面後,頁面內容依然停留在buylist,但高亮的菜單卻變成了userlist)。

如果要解決這個bug,就需要在本地儲存(刷新不改變儲存狀態) menu 狀態,本地儲存可以選擇不同的方案,在此不做討論,但可以肯定的是DOM 本地儲存控制menu 高亮的方案在專案逐漸變大以後會變得難以維護。

現在是 vuex 登場的時候了。

使用vuex 進行選單管理

使用vuex 進行選單管理需要在開發前就規劃好選單的層級,以便在vuex 中分配state mutations

規劃層級

確定專案中哪些是一級選單,哪些是二級選單,以此類推… 這裡要注意的是,為簡化操作,同等級選單都以不同名稱命名,這樣在vuex 中就不需要專注在選單屬於那個頁面,只專注在狀態就好。選單層級通常如下:

|-root
| |
| |-first-menu1
| |   |- second-menu1
| |   |- second-menu2
| |   |- second-menu3
| |
| |-first-menu2
|    |- second-menu3
|    |- second-menu4
|    |- second-menu5

在vuex 指派`state` 和`mutations` 

不同層級的選單分別佔用一個`state`,至於`mutations`,本例不同`state` 分別對應寫了一個`mutations`,實際工作中為了更大成都減少程式碼復用,對於menu 的狀態管理可以只寫一個`mutations`,透過傳參判斷是更改哪個層級及對應的menu。

要注意的是 vuex 在頁面刷新後狀態會重新初始化,這顯然和管理選單所需功能不符(除了主動觸發,其他操作不能對選單產生影響)。可以透過vuex-persistedstate 改變vuex 預設生命週期,下面範例程式碼將vuex 狀態儲存在了cookie 中:

js

const store = new Vuex.Store({
 state: {
  // 初始化
  activeFirstMenu: &#39;firstMenu1&#39;,
  activeSecondMenu : &#39;secondMenu1&#39;,
 },
 mutations: {
  // 更改一级菜单
  changeFirstActiveMenu (state, menu) {
   state.activeFirstMenu = menu;
  },
  // 更改二级二级菜单
  changeSecondActiveMenu (state, menu) {
   state.activeSecondMenu = menu;
  }
 },
});

元件中渲染

在template 動態載入高亮class,透過vuex 中state 控制:

<p class="subMenu">
 <span :class="{ activeSecondMenu: activeMenu.secondMenu1 }" @click="menuClicked(&#39;secondMenu1&#39;)">secondMenu1</span>
</p>
<p class="subMenu">
 <span :class="{ activeSecondMenu: activeMenu.secondMenu2 }" @click="menuClicked(&#39;secondMenu2&#39;)">secondMenu2</span>
</p>
<p class="subMenu">
 <span :class="{ activeSecondMenu: activeMenu.secondMenu3 }" @click="menuClicked(&#39;secondMenu3&#39;)">secondMenu3</span>
</p>

寫js 時有個技巧:路由path 和對應高亮的menu 名稱最好相同,因為路由跳轉和高亮menu 直接相關,這樣可以減少一個參數:

data () {
 return {
  // 初始化
  activeMenu: {
   // menu 名称相同,和对应路由的 path 相同
   secondMenu1: &#39;&#39;,
   secondMenu2: &#39;&#39;,
   secondMenu3: &#39;&#39;,
  },
 };
},
computed: {
 activeMenuName () {
  // 检测 vuex 中 activeSecondMenu 的变化
  return this.$store.state.activeSecondMenu;
 }
},
methods: {
 menuClicked(path) {
  // 取消当前 tab 高亮
  this.activeMenu[this.activeMenuName] = false;

  // 更新 vuex 状态及 menu 高亮
  this.$store.commit("changeSecondActiveMenu", path);
  this.activeMenu[this.activeMenuName] = true;

  // 路由跳转 path 和对应 menu 名称相同 
  this.$router.push(`/somePath/${path}`);
 },
 init () {
  // 刷新页面重置正确高亮菜单tab
  this.activeMenu[this.activeMenuName] = true;
 },
},
mounted: {
 this.init();
},

其他

#對於vuex 的最佳化

上文有談到,實際工作中為了更大程度實現程式碼重複使用,對於某個類別的狀態管理可以只寫一個mutations ,透過傳參(Payload )判斷更改內容。還是以menu 管理為例,可進行下面的最佳化:

vuex 最佳化後如下:

const store = new Vuex.Store({
 // 其他代码略

 mutations: {
  // 优化后代码,合并 changeFirstActiveMenu 和 changeSecondActiveMenu
  changeActiveMenu (state, menuInfo) {
   state[menuInfo.menuHierarchy] = menuInfo.name;
  }
 }
});

元件js 部分最佳化後如下:

methods: {
 menuClicked(path) {
  // 其他代码略高亮

  // 优化后代码:更改一级和二级菜单触发同个 mutation
  this.$store.commit("changeActiveMenu", {
   menuHierarchy: &#39;activeFirstMenu&#39;,
   name: path,
  });

  this.$store.commit("changeActiveMenu", {
   menuHierarchy: &#39;activeSecondMenu&#39;,
   name: path,
  });

  // 其他代码略
 },
},

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

使用React如何防止重複渲染

#使用vue如何實作grid-layout功能

詳細介紹在Bootstrap中為Modal新增拖曳功能

#在JS中如何實作預覽效果

##使用three.js製作一個專案

以上是如何使用vuex實現選單管理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn