动态组件驱动的标签页架构(简单来说:一个页面包含许多Tabs页面,这些Tabs页面渲染逻辑)

整体渲染思路:

  1. TabMenu创建 → 解析路由配置 → 生成tabPanes数据

  2. TabPanes接收数据 → 遍历创建el-tab-pane

  3. 用户点击标签 → activeName改变

  4. Vue发现activeName匹配 → 调用对应的componentName函数

  5. loadView执行 → require()加载组件文件

  6. 组件加载完成 → 渲染到页面

  7. keep-alive缓存 → 切换时保持状态

复制代码
// TabMenu.vue

<template>
  <div>
    <TabPanes :key="$route.path" :tabPanes.sync="tabPanes" />
  </div>
</template>

<script>
import TabPanes from "@/components/TabPane/tab-pane";
function loadView(view) {
  return resolve => require([`@/views/${view}`], resolve);
}

export default {
  components: {
    TabPanes
  },
  data() {
    return {
      tabPanes: null
    };
  },
  created() {
    this.init();
  },
  methods: {
    init() {
      const tabs = this.$route.meta.tabs;
      this.tabPanes = tabs.map(item => {
        return {
          title: item.name,
          name: item.code,
          componentName: loadView([item.component])
        };
      });
    }
  },

  watch: {
    "$route.path": function(newVal, oldVal) {
      this.init();
    }
  }
};
</script>

// tab-pane.vue

<template>
  <el-tabs
    v-model="activeName"
    :type="tabType"
    @tab-click="tabClick"
    class="tab-panes"
  >
    <template>
      <el-tab-pane
        v-for="(tab, index) in tabPanes"
        :key="tab.title+index"
        :label="tab.title"
        :lazy="true"
        :name="tab.name"
      >
        <keep-alive>
          <component
            class="content"
            v-if="activeName === tab.name"
            :is="tab.componentName"
          />
        </keep-alive>
      </el-tab-pane>
    </template>
  </el-tabs>
</template>

<script>
//这是tabPane要显示的组件

export default {
  name: "TabPanes",
  props: {
    tabPanes: {
      type: Array,
      default: () => []
    },

    tabType: {
      type: String,
      default: ""
    }
  },

  data() {
    return {
      activeName: null
    };
  },

  created() {
    this.setActiveTab();
  },
  mounted(){
    this.setActiveTab();
  },
  watch: {
    activeName: {
      handler(val) {
        if (val) {
          this.$router.replace({
            query: { tab: val },
            params: { ...this.$route.params }
          });
        }
      },
    },
    "$route.query.tab"(val) {
      this.activeName = val || '';
    },
    tabPanes: {
      handler(val) {
        if (val.length > 0 && !this.$route.query.tab) {
          this.activeName = val[0].name;
        }
      }
    },
  },

  methods: {
    setActiveTab() {
      const tabFromQuery = this.$route.query.tab;
      const isValidTab = tabFromQuery && this.tabPanes.some(tab => tab.name === tabFromQuery);

      this.activeName = isValidTab ? tabFromQuery : (this.tabPanes[0] && this.tabPanes[0].name || '');
    },
    tabClick(tab) {
      this.activeName = tab.name;
    },
  }
};
</script>

<style lang="scss" scoped>
.el-tabs {
  position: absolute;
  inset: 0;
  overflow: overlay;

  & ::v-deep .el-tabs__header {
    padding: 0;
    position: relative;
    margin: 0 0 0 10px;
    border-top: 1px solid #bfcbd9;
  }

  & ::v-deep .el-tabs__nav-wrap {
    background-color: #fff !important;
    padding-left: 10px;
  }

  &::-webkit-scrollbar {
    width: 10px;
    background: transparent;
  }

  &::-webkit-scrollbar-thumb {
    border-radius: 9px;
    background-color: #c0c0c0;
  }
}
</style>

TabMenu.vue 是在哪里被调用的?

结论:TabMenu.vue 不是在前端代码中直接调用的,而是通过后端返回的动态路由配置来加载的!

整个过程是:

1.用户访问某个URL(比如 /xxx )

2.权限系统检查用户是否有该页面权限

3.后端返回菜单配置,其中包含:

{

"path": "/xxx",

"component": "component/TabMenu",

"meta": {

"tabs": [

{"code": "xxx", "name": "tab页面名称", "component": "xx/xx/xx"}

]

}

}

4.前端动态加载 component/TabMenu.vue 组件

5.TabMenu执行,解析 meta.tabs 配置,渲染子页面

这就是为什么你找不到直接调用的原因!
TabMenu是动态路由系统的一部分,由后端菜单配置驱动,而不是在前端代码中硬编码引用的。

这种设计的优势:
权限灵活: 可以动态控制谁可以访问哪些页面
菜单可配置: 管理员可以配置页面结构,无需修改前端代码
**组件按需加载:**只在需要时才加载对应的Vue组件

相关推荐
灵感__idea3 小时前
Hello 算法:贪心的世界
前端·javascript·算法
GreenTea5 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
killerbasd6 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
吴声子夜歌7 小时前
ES6——二进制数组详解
前端·ecmascript·es6
码事漫谈7 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
ZC跨境爬虫7 小时前
【爬虫实战对比】Requests vs Scrapy 笔趣阁小说爬虫,从单线程到高效并发的全方位升级
前端·爬虫·scrapy·html
爱上好庆祝7 小时前
svg图片
前端·css·学习·html·css3
橘子编程7 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
王夏奇7 小时前
python中的__all__ 具体用法
java·前端·python
叫我一声阿雷吧8 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint