Vue開發實例(十)Tabs標簽頁打開、關閉與路由之間的關系

創建標簽頁

  • 一、創建標簽頁
  • 二、點擊菜單展示新標簽頁
    • 1、將標簽數據作為全局使用
    • 2、菜單點擊增加標簽頁
    • 3、處理重復標簽
    • 4、關閉標簽頁
  • 三、點擊標簽頁操作
    • 問題1:點擊標簽頁選中菜單進行高亮展示
    • 問題2:點擊標簽頁路由也要跳轉
  • 四、解決bug


先展示最終效果
在這里插入圖片描述

一、創建標簽頁

  1. 創建一個Tabs/index.vue頁面
<template><div><el-tabs v-model="editableTabsValue" type="card" closable><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabss",data() {return {editableTabsValue: "1",editableTabs: [{title: "首頁",name: "1",content: "首頁",},{title: "Tab 1",name: "2",content: "Tab 1 content",},{title: "Tab 2",name: "3",content: "Tab 2 content",},],tabIndex: 1,};},
};
</script><style scoped>
div{height: auto;
}
</style>
  1. 修改Index.vue頁面,在頁面的路由錨點 router-view上方引入此頁面
    在這里插入圖片描述
    頁面效果
    在這里插入圖片描述

二、點擊菜單展示新標簽頁

1、將標簽數據作為全局使用

(1)將數據放到store.js中,作為全局

import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './module/moduleA.js';
import moduleB from './module/moduleB.js';Vue.use(Vuex)const state = {username: '牛牛',userState: 0,menu_data: [],isLoadRoute: false,editableTabsValue: '1',editableTabs: [{title: '首頁',name: '首頁',content: '首頁'},{title: 'Tab 1',name: '2',content: 'Tab 1 content'},{title: 'Tab 2',name: '3',content: 'Tab 2 content'}]
}
const mutations = {setLoadRoute(state, data) {state.isLoadRoute = data},setUser(state, name) {state.username = name},setUserState(state, data) {state.userState += data},setMenuData(state, data) {state.menu_data = data},}
const getters = {getUserState(state) {let data;if (state.userState == 0) {data = '無效'} else {data = state.userState + '級'}return data;}
}
const modules = {a: moduleA,b: moduleB
}export default new Vuex.Store({state,mutations,getters,modules
})

(2)Tabs/index.vue 中的這兩個數據 editableTabsValueeditableTabs 就從store中獲取

注意:

  • 如果你的在data中這樣寫,可能會無法正常顯示,建議用computed 方式來寫。
<template><div><el-tabs v-model="editableTabsValue" type="card" closable><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabs",data() {return {};},computed: {editableTabsValue: {get() {return this.$store.state.editableTabsValue;},set(val) {this.$store.state.editableTabsValue = val;},},editableTabs: {get() {return this.$store.state.editableTabs;},set(val) {this.$store.state.editableTabs = val;},},},
};
</script><style scoped>
div {height: auto;
}
</style>

頁面效果是一樣的
在這里插入圖片描述

2、菜單點擊增加標簽頁

(1)在 store/index.js 中將寫死的數據editableTabs 內容刪除,只剩下首頁的那條
(2)在mutations添加 editableTabs 數據變更的方法 addEditableTabs,因為我定義的菜單數據的時候,沒有title屬性,所以這里我都用title來代表

參考代碼:

import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './module/moduleA.js';
import moduleB from './module/moduleB.js';Vue.use(Vuex)const state = {username: '牛牛',userState: 0,menu_data: [],isLoadRoute: false,editableTabsValue: '1',editableTabs: [{title: '首頁',name: '首頁',content: '首頁'}]
}
const mutations = {setLoadRoute(state, data) {state.isLoadRoute = data},setUser(state, name) {state.username = name},setUserState(state, data) {state.userState += data},setMenuData(state, data) {state.menu_data = data},addEditableTabs(state, tab) {state.editableTabs.push({title: tab.name,name: tab.name})state.editableTabsValue = tab.name}
}
const getters = {getUserState(state) {let data;if (state.userState == 0) {data = '無效'} else {data = state.userState + '級'}return data;}
}
const modules = {a: moduleA,b: moduleB
}export default new Vuex.Store({state,mutations,getters,modules
})

(3)給Aside/index.vue菜單增加點事件,selectMenu方法

<template><div style="height: 100%"><el-menubackground-color="#545c64"text-color="#ffffff"active-text-color="#ffd04b"class="el-menu-vertical-demo"router><el-menu-item:index="item.path"v-for="item in menu_data":key="item.name"@click="selectMenu(item)"><i :class="item.icon"></i>{{ item.name }}</el-menu-item></el-menu></div>
</template><script>
export default {name: "Aside",data() {return {};},computed: {menu_data: {get() {return this.$store.state.menu_data;},},},methods: {selectMenu(item) {this.$store.commit("addEditableTabs", item);},},
};
</script><style scoped>
.el-icon-location,
.el-icon-document,
.el-icon-setting {display: inline-flex;align-items: center;justify-content: center;
}
</style>

頁面效果
在這里插入圖片描述
問題:出現重復菜單名稱標簽

3、處理重復標簽

store/index.js文件中的addEditableTabs 中判斷,如果數據中已經有了,則不重復添加,只需切換即可
在這里插入圖片描述

頁面效果
在這里插入圖片描述
現在就只有兩個標簽了,目前展示正常,但是沒法關閉

4、關閉標簽頁

標簽頁添加關閉事件

el-tabs標簽中添加 @tab-remove="removeTab",在method添加對應的方法

<template><div><el-tabsv-model="editableTabsValue"type="card"closable@tab-remove="removeTab"><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabs",data() {return {};},methods: {removeTab(targetName) {let tabs = this.editableTabs;let activeName = this.editableTabsValue;if (activeName === targetName) {tabs.forEach((tab, index) => {if (tab.name === targetName) {let nextTab = tabs[index + 1] || tabs[index - 1];if (nextTab) {activeName = nextTab.name;}}});}this.editableTabsValue = activeName;this.editableTabs = tabs.filter((tab) => tab.name !== targetName);},},computed: {editableTabsValue: {get() {return this.$store.state.editableTabsValue;},set(val) {this.$store.state.editableTabsValue = val;},},editableTabs: {get() {return this.$store.state.editableTabs;},set(val) {this.$store.state.editableTabs = val;},},},
};
</script><style scoped>
div {height: auto;
}
</style>

頁面效果
在這里插入圖片描述

問題:

  1. 選中菜單,側邊欄沒有進行對應的高亮展示
  2. 關閉了“一級菜單2”,但是頁面內容還停留在“一級菜單2”,其實就是路由沒有變

三、點擊標簽頁操作

問題1:點擊標簽頁選中菜單進行高亮展示

  1. 在Aside/index.vue中給 el-menu 設置屬性 default-active
:default-active="this.$store.state.editableTabsValue"
  1. 將原來代碼el-menu-item的index設置為"item.name"
:index="item.name"
  1. 加入路由跳轉代碼

因原來菜單點擊,會根據index屬性來跳轉,index原來是path(路由地址),現在index屬性更改為name了,則跳轉不會生效,修改原來的router.js的代碼,動態創建路由加入name屬性(name:item.name),方便跳轉。

修改router/index.js 代碼

let oRouters = router.options.routes;
const buildRouter = ()=>{let data = store.state.menu_data;data.forEach(item=>{let new_router = {path:item.path,name:item.name,component:() => import('./components/'+item.component+'.vue')}oRouters[0].children.push(new_router);})router.addRoutes(oRouters)
}

Aside/index.vue的 selectMenu方法中,加入路由跳轉代碼(根據name跳轉),僅需一行代碼即可。

selectMenu(item){//點擊菜單跳轉路由this.$router.push({name:item.name})this.$store.commit("addEditableTabs",item);
}

頁面效果,可以實現點擊標簽頁,菜單跟著高亮顯示了
在這里插入圖片描述
Aside/index.vue 頁面代碼

<template><div style="height: 100%"><el-menubackground-color="#545c64"text-color="#ffffff"active-text-color="#ffd04b"class="el-menu-vertical-demo"router:default-active="this.$store.state.editableTabsValue"><el-menu-item:index="item.name"v-for="item in menu_data":key="item.name"@click="selectMenu(item)"><i :class="item.icon"></i>{{ item.name }}</el-menu-item></el-menu></div>
</template><script>
export default {name: "Aside",data() {return {};},computed: {menu_data: {get() {return this.$store.state.menu_data;},},},methods: {selectMenu(item) {//點擊菜單跳轉路由this.$router.push({ name: item.name });this.$store.commit("addEditableTabs", item);},},
};
</script><style scoped>
.el-icon-location,
.el-icon-document,
.el-icon-setting {display: inline-flex;align-items: center;justify-content: center;
}
</style>

問題2:點擊標簽頁路由也要跳轉

上面遺留的問題2,點擊標簽頁,標簽頁下方的頁面沒有跟著跳轉,下面修改這個問題

  1. 在Tabs頁面的 el-tabs 添加 tab-click 事件
  2. 添加方法,利用路由的name來跳轉
<template><div><el-tabsv-model="editableTabsValue"type="card"closable@tab-remove="removeTab"@tab-click="clickTab"><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabs",data() {return {};},methods: {removeTab(targetName) {let tabs = this.editableTabs;let activeName = this.editableTabsValue;if (activeName === targetName) {tabs.forEach((tab, index) => {if (tab.name === targetName) {let nextTab = tabs[index + 1] || tabs[index - 1];if (nextTab) {activeName = nextTab.name;}}});}this.editableTabsValue = activeName;this.editableTabs = tabs.filter((tab) => tab.name !== targetName);},clickTab(target) {this.$router.push({ name: target.name });},},computed: {editableTabsValue: {get() {return this.$store.state.editableTabsValue;},set(val) {this.$store.state.editableTabsValue = val;},},editableTabs: {get() {return this.$store.state.editableTabs;},set(val) {this.$store.state.editableTabs = val;},},},
};
</script><style scoped>
div {height: auto;
}
</style>

效果展示
在這里插入圖片描述

四、解決bug

  1. 關閉菜單后,菜單對應的路由沒有跟著跳轉
    僅需在關閉標簽的方法removeTab,最后加上以下代碼
this.$router.push({name:activeName})
  1. 首頁不允許關閉
    在關閉標簽的方法removeTab ,執行關閉之前,加入以下代碼
if(targetName=='首頁'){return ;
}
  1. 完整removeTab 代碼
removeTab(targetName) {let tabs = this.editableTabs;let activeName = this.editableTabsValue;if(targetName=='首頁'){return ;}if (activeName === targetName) {tabs.forEach((tab, index) => {if (tab.name === targetName) {let nextTab = tabs[index + 1] || tabs[index - 1];if (nextTab) {activeName = nextTab.name;}}});}this.editableTabsValue = activeName;this.editableTabs = tabs.filter(tab => tab.name !== targetName);this.$router.push({name:activeName})
}
  1. 還有一個潛藏的bug就是打開、關閉的順序問題,先關閉前面的菜單會報錯,后面解決

在這里插入圖片描述報錯代碼如下

Uncaught runtime errors:Avoided redundant navigation to current location: "/index/menu2".NavigationDuplicated: Avoided redundant navigation to current location: "/index/menu2".at createRouterError (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1720:15)at createNavigationDuplicatedError (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1708:15)at HTML5History.confirmTransition (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1946:18)at HTML5History.transitionTo (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1887:8)at HTML5History.push (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2165:10)at eval (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2510:22)at new Promise (<anonymous>)at VueRouter.push (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2509:12)at VueComponent.removeTab (webpack-internal:///./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Tabs/index.vue?vue&type=script&lang=js:29:20)at invokeWithErrorHandling (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:2903:26)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717480.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717480.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717480.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android 基礎入門 基礎簡介

1. 觀察App運行日志 2.Android 開發設計的編程語言 koltin Java c c 3.工程目錄結構 4.Gradle 5.build.gradle 文件解析 plugins {id("com.android.application")//用了哪些插件 主配置文件版本控制 所以這里不用寫版本 }android {namespace "com.tiger.myap…

【C++】每周一題——2024.3.3(手滑再寫一篇)

題目 Cpp 【問題描述】 輸入一個由若干個以空格分隔的單詞組成的英文文章&#xff0c;求文章中最短的單詞&#xff08;文章以英文句點”.”結束&#xff0c;且字符數不超過200&#xff09;. 【輸入格式】 一行&#xff0c;表示輸入的英文文章。 【輸出格式】 一行&#xff0c;表…

反向代理與負載均衡

目錄 反向代理 負載均衡 反向代理 代理角色&#xff1a; 正常情況下&#xff0c;客戶端&#xff08;如瀏覽器&#xff09;直接與服務器通信&#xff0c;但在反向代理中&#xff0c;Nginx充當客戶端和服務器之間的中介。客戶端向Nginx發送請求&#xff0c;而Nginx負責將請求轉…

基于springboot+vue的二手車交易系統

博主主頁&#xff1a;貓頭鷹源碼 博主簡介&#xff1a;Java領域優質創作者、CSDN博客專家、阿里云專家博主、公司架構師、全網粉絲5萬、專注Java技術領域和畢業設計項目實戰&#xff0c;歡迎高校老師\講師\同行交流合作 ?主要內容&#xff1a;畢業設計(Javaweb項目|小程序|Pyt…

金三銀四,風控建模面試全攻略:從簡歷準備到面試技巧

隨著春天的到來,招聘市場的 “金三銀四” 也悄然而至。公眾號的小伙伴問我有沒有面試相關指導課程,上完課后,把整理的部分材料通過文章分享給更多有需要的朋友。預祝大家順利獲得心儀的職位。本文將從簡歷準備、面試注意事項以及高頻面試問題三個方面,為你提供一份全面的風…

字符串判空錯誤

字符串判空錯誤 前端傳來的請求數據&#xff0c;若用只用String為null判斷&#xff0c;則忽略了str“”的情況&#xff0c;此時str不空&#xff0c;但str.length()0 RequestMapping(path "/add", method RequestMethod.POST)ResponseBodypublic String addDiscuss…

C++進階(二) 多態

一、多態的概念 多態的概念&#xff1a;通俗來說&#xff0c;就是多種形態&#xff0c; 具體點就是去完成某個行為&#xff0c;當不同的對象去完成時會 產生出不同的狀態。舉個栗子&#xff1a;比如買票這個行為&#xff0c;當普通人買票時&#xff0c;是全價買票&#xff1b;學…

Linux 查詢端口被占用命令

Linux 查詢端口被占用命令 1、lsof -i:端口號 用于查看某一端口的占用情況&#xff0c;比如查看8000端口使用情況&#xff0c;lsof -i:8000 lsof -i:8080&#xff1a;查看8080端口占用 lsof abc.txt&#xff1a;顯示開啟文件abc.txt的進程 lsof -c abc&#xff1a;顯示abc進…

Java中的List

List集合的特有方法 方法介紹 方法名描述void add(int index,E element)在此集合中的指定位置插入指定的元素E remove(int index)刪除指定索引處的元素&#xff0c;返回被刪除的元素E set(int index,E element)修改指定索引處的元素&#xff0c;返回被修改的元素E get(int inde…

動態規劃5,粉刷房子,買賣股票的最佳時期

粉刷房子 思路&#xff1a; 1.經驗題目要求 dp[i][0] 表示&#xff1a;粉刷到 i 位置的時候&#xff0c;最后一個位置粉刷上紅色&#xff0c;此時的最小花費。 dp[i][1] 表示&#xff1a;粉刷到 i 位置的時候&#xff0c;最后一個位置粉刷上藍色&#xff0c;此時的最小花費。…

mybatis開發一個分頁插件、mybatis實現分頁、mybatis攔截器

mybatis開發一個分頁插件、mybatis實現分頁、mybatis攔截器 通過官網的mybatis插件說明可知&#xff0c;我們可以通過攔截器進行開發一個插件。 例如這樣的&#xff1a; UserMapper mapper sqlSession.getMapper(UserMapper.class);// 開始分頁MagicPage.startPage(1, 3);//…

Javascript:類型轉換

一、前言 prompt與表達單取過來的值默認為string類型 二、正文 1.隱式轉換 某些運算符被執行的時候&#xff0c;系統內部自動將數據類型進行轉換。 規則&#xff1a; 好兩邊只要有一個是字符串&#xff0c;都會把另外一個轉成字符串。 除了以外的算術運算符&#xff0c;比如…

Linux:線程的概念

個人主頁 &#xff1a; 個人主頁 個人專欄 &#xff1a; 《數據結構》 《C語言》《C》《Linux》 文章目錄 前言一、線程的概念線程代碼的簡單示例 總結 前言 本文是對于線程概念的知識總結 一、線程的概念 在課本上&#xff0c;線程是比進程更輕量級的一種指向流 或 線程是在…

VS Code 的粘性滾動預覽 - 類似于 Excel 的凍結首行

VS Code 的粘性滾動預覽 - 類似于 Excel 的凍結首行功能&#xff0c;即滾動 UI 顯示當前源代碼范圍。便于在代碼行數比較多的時候更好的知道自己所在的位置。粘性滾動UI 顯示用戶在滾動期間所處的范圍&#xff0c;將顯示編輯器頂部所在的類/接口/命名空間/函數/方法/構造函數&a…

4、Linux-常用命令(二)

目錄 一、搜索命令 1、命令搜索命令 2、文件搜索命令find。格式&#xff1a;find [搜索范圍] [搜索條件]。 3、字符串搜索命令grep 二、幫助命令 1、man【詳細的幫助】 2、--help【簡要的幫助】 三、壓縮與解壓命令 1、.zip格式 2、.gz格式 3、打包 四、關機和重啟命…

【大廠AI課學習筆記NO.57】(10)分類任務的評價指標

我們實際做的是一個分類任務。 在人工智能深度學習項目中&#xff0c;分類任務是指一種特定的任務類型&#xff0c;即預測結果是離散值的任務。具體來說&#xff0c;分類任務的目標是將輸入數據劃分到不同的類別中。這些類別可以是二分類&#xff08;如垃圾郵件分類&#xff0c…

理解這幾個安全漏洞,你也能做安全測試

01 短信炸彈 1、漏洞描述 短信轟炸攻擊是常見的一種攻擊&#xff0c;攻擊者通過網站頁面中所提供的發送短信驗證碼的功能處&#xff0c;通過對其發送數據包的獲取后&#xff0c;進行重放&#xff0c;如果服務器短信平臺未做校驗的情況時&#xff0c;系統會一直去發送短信&…

函數式響應式編程(FRP):構筑靈活動態的應用程序

FRP&#xff08;Functional Reactive Programming&#xff0c;函數式響應式編程&#xff09;是一個編程范式&#xff0c;它結合了函數式編程和響應式編程的原則&#xff0c;用于處理時間變化的數據和響應性系統。FRP 讓開發者能夠以聲明式地方式來構建響應用戶輸入、網絡請求或…

【vue3 路由使用與講解】vue-router : 簡潔直觀的全面介紹

# 核心內容介紹 路由跳轉有兩種方式&#xff1a; 聲明式導航&#xff1a;<router-link :to"...">編程式導航&#xff1a;router.push(...) 或 router.replace(...) &#xff1b;兩者的規則完全一致。 push(to: RouteLocationRaw): Promise<NavigationFailur…

JVM內部世界(內存劃分,類加載,垃圾回收)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要內容&#xff1a;JVM內部世界(內存劃分,類加載,垃圾回收) 關于JVM的學習主要掌握三方面: JVM內存區的劃分類加載垃圾回收 一.JVM內存區的劃分 當一個Java進程開始執行時,JVM會首先向操作系統申…