zoukankan      html  css  js  c++  java
  • 爱是在雪地里写诗,边写边消失:父子级路由切换,组件不可见之殇

    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 路由独享的守卫,点击进入其子路由B/C,beforeEnter是没有反应的(一开始我就掉进这个坑里面,以为路由没到呢,但其实这个beforeEnter是这个路由独享的!例如下面就是Foo这__路由地址专用__,换了别的路由都不会触发!!!)

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          beforeEnter: (to, from, next) => {
            // ...
          }
        }
      ]
    })
    

    导航守卫 | Vue Router (vuejs.org)

    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啊,其实还有很多不明白。需要多多练习使用。

    人生到处知何似,应似飞鸿踏雪泥。
  • 相关阅读:
    搜刮一些开源项目的APP
    iOS Crash文件的解析
    iOS中RGB颜色转换
    随笔杂记
    iOS字体
    方法总结
    经验点滴
    个人理解
    OC 知识点回顾
    IOS UI 笔记整理回顾
  • 原文地址:https://www.cnblogs.com/lepanyou/p/15783519.html
Copyright © 2011-2022 走看看