創建標簽頁
- 一、創建標簽頁
- 二、點擊菜單展示新標簽頁
- 1、將標簽數據作為全局使用
- 2、菜單點擊增加標簽頁
- 3、處理重復標簽
- 4、關閉標簽頁
- 三、點擊標簽頁操作
- 問題1:點擊標簽頁選中菜單進行高亮展示
- 問題2:點擊標簽頁路由也要跳轉
- 四、解決bug
先展示最終效果
一、創建標簽頁
- 創建一個
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>
- 修改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
中的這兩個數據 editableTabsValue
和 editableTabs
就從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>
頁面效果
問題:
- 選中菜單,側邊欄沒有進行對應的高亮展示
- 關閉了“一級菜單2”,但是頁面內容還停留在“一級菜單2”,其實就是路由沒有變
三、點擊標簽頁操作
問題1:點擊標簽頁選中菜單進行高亮展示
- 在Aside/index.vue中給
el-menu
設置屬性default-active
:default-active="this.$store.state.editableTabsValue"
- 將原來代碼
el-menu-item
的index設置為"item.name"
:index="item.name"
- 加入路由跳轉代碼
因原來菜單點擊,會根據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,點擊標簽頁,標簽頁下方的頁面沒有跟著跳轉,下面修改這個問題
- 在Tabs頁面的
el-tabs
添加tab-click
事件 - 添加方法,利用路由的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
- 關閉菜單后,菜單對應的路由沒有跟著跳轉
僅需在關閉標簽的方法removeTab,最后加上以下代碼
this.$router.push({name:activeName})
- 首頁不允許關閉
在關閉標簽的方法removeTab ,執行關閉之前,加入以下代碼
if(targetName=='首頁'){return ;
}
- 完整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})
}
- 還有一個潛藏的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)