愛是在雪地裡寫詩,邊寫邊消失:父子級路由切換,元件不可見之殤
阿新 • • 發佈:2022-01-10
0. 緣起
我有1個el-menu生成的選單,下面有個帶著router-view的el-main,結果側邊欄的某個選項存在著點選跳轉到空白頁面的陰間BUG。那麼,耗費在下四小時心血找到的BUG,究竟是個什麼東西呢?
1. 看不見的BUG
這個BUG的表現形式還真是看不見對應元件。我有ABC三個元件,其中A作為BC的入口,點選el-menu-item裡的A,再在表格之中點選不同項會跳轉到對應的B頁面或者C頁面。
然後測試的時候,我就發現有個蜜汁BUG,點選A中的BC對應項還是A的元件,BC根本出現都沒出現。我看路由已經改變,beforeEach
全域性路由守衛也顯示跳轉到B/C對應的路由了。
不過如果設定了A的beforeEnter
beforeEnter
是沒有反應的(一開始我就掉進這個坑裡面,以為路由沒到呢,但其實這個beforeEnter
是這個路由獨享的!例如下面就是Foo這__路由地址專用__,換了別的路由都不會觸發!!!)
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
2. 過程
那麼我是怎麼發現這個BUG的根源在B/C上面的呢?因為我拿了個外面的D路由來作為A點選表格跳轉的新路由,這個D點選就出現了,正是我需要的效果!所以我開始思索為什麼作為子元件的這兩個不會出現在父元件裡,搜了一下,擦答案就是【使用vue-router的子路由,需要在父元件利用router-view佔位。】
非常弱智的錯誤,我特麼反應過來就知道為嘛了,因為A元件裡我沒有放router-view
!!!放了個測試一下,擦,B/C就能冒出來了。
不過我需要的效果是點選A表格內容,B/C取代A出現,需要出現在與A相同的router-view
窗口裡!所以這兩玩意應該和A是同級的!但是不應該在el-menu中出現,所以要在這裡對它進行處理。
3. 程式碼
3.1 router.js
// Transfer Vice Page
{
path: "IEC104",
name: "IEC104",
component: () => import("@/views/demon/demonTransfer/IEC104"),
meta: {
title: "IEC104",
permissions: ["admin", "system:magicBox:list"]
},
hidden: true,
},
這裡的hidden是在下一步el-menu佈局中剔除無關佈局項的重要flag
3.2 el-menu佈局
<template>
<el-container class="zd-router-layout">
<el-aside
width="256px"
v-if="'horizontal' === layout"
:style="{ height: height }"
>
<el-menu
default-active="2"
:default-active="defaultActive"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
router
active-text-color="#ffd04b"
>
<component
:is="
router.children && router.children.length
? 'el-submenu'
: 'el-menu-item'
"
v-for="router in routers"
:key="router.name"
:index="`/demon-box/demon-detail/${router.path}`"
>
<span
slot="title"
v-if="!router.children || !router.children.length"
>{{ router.meta.title }}</span
>
<template slot="title" v-else>{{ router.meta.title }}</template>
<component
is="el-menu-item"
v-for="child in router.children"
:key="child.name"
:index="`/demon-box/demon-detail/${router.path}/${child.path}`"
>
<span slot="title">{{ child.meta.title }}</span>
</component>
</component>
</el-menu>
</el-aside>
<el-header v-else>
<el-menu
mode="horizontal"
router
:default-active="defaultActive"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
>
<component
:is="
router.children && router.children.length
? 'el-submenu'
: 'el-menu-item'
"
v-for="router in routers"
:key="router.name"
:index="`/demon-box/demon-detail/${router.path}`"
>
<span
slot="title"
v-if="!router.children || !router.children.length"
>{{ router.meta.title }}</span
>
<template slot="title" v-else>{{ router.meta.title }}</template>
<component
is="el-menu-item"
v-for="child in router.children"
:key="child.name"
:index="`/demon-box/demon-detail/${router.path}/${child.path}`"
>
<span slot="title">{{ child.meta.title }}</span>
</component>
</component>
</el-menu>
</el-header>
<el-main :style="{ height: mainHeight }">
<router-view />
</el-main>
</el-container>
</template>
<script>
import { demonRoutes } from "@/router";
import { mapGetters } from "vuex";
export default {
name: "routerLayout",
data() {
return {};
},
watch: {
layout: {
handler(val) {
this.refreshRoute();
},
},
},
mounted() {
this.$baseEventBus.$on("deliverRoute", (data) => {
this.$router.push(data);
});
},
beforeDestroy() {
this.$baseEventBus.$off("deliverRoute");
},
computed: {
...mapGetters({
layout: "settings/layout",
}),
routers: {
get() {
return demonRoutes
.map((item) => {
if (item.hidden) {
return;
}
if (item.children) {
item.children = item.children.filter((ele) => !ele.hidden);
}
return item;
})
.filter((key) => key); // Filter null page (Like IEC104 & Modbus)
},
},
defaultActive: {
get() {
return this.$route.path;
},
},
height: {
get() {
return "calc(100vh - 200px)";
},
},
mainHeight: {
get() {
return "vertical" === this.layout
? "calc(100vh - 240px)"
: "calc(100vh - 180px)";
},
},
},
methods: {
async refreshRoute() {
this.$baseEventBus.$emit("reload-router-view");
this.pulse = true;
setTimeout(() => {
this.pulse = false;
}, 1000);
},
},
};
</script>
<style lang="scss" scoped>
.zd-router-layout {
.el-aside {
background-color: #545c64;
}
.el-main {
overflow: hidden;
padding: 0;
overflow-y: auto;
}
}
</style>
4. 想法
基礎不牢,地動山搖。
最近有點悠閒了,看了別的內容,比如一點點GO和MONGODB,但自己這恰飯的東西,像是Vue啊JS啊ES6啊,其實還有很多不明白。需要多多練習使用。
人生到處知何似,應似飛鴻踏雪泥。