vue3 tab切换 动态组件

vue3 tab切换 动态组件

先看一张图
vue3 tab切换 动态组件_第1张图片

具体代码:

组件实例信息

如果你把组件实例放到Reactive Vue会给你一个警告:Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw or using shallowRef instead of ref.
Vue 收到一个组件,它被做成一个反应性对象。这可能会导致不必要的性能开销,应通过使用“markRaw”标记组件或使用“shallowRef”而不是“ref”来避免。

index.vue

<template>
  <a-layout class="layout">
    <a-layout-content class="main-container">
      <div class="data-bar" :class="{ collapsed: collapsed }">
        <div class="data-bar-container">
          <div class="data-bar-icon-box">
            <img :src="logo" @click="handleBackDashboard" />
          </div>
          <div class="data-bar-button" @click="handleBack">
            <LeftOutlined />
            返回上一页
          </div>

        </div>
      </div>
      <a-affix offset-top="0">
        <div class="tab-bar">
   
          <div class="tabs">
            <template v-for="(tab, tabIndex) in tabs" :key="tabIndex">
              <div
                v-if="tab.show"
                :class="'tab' + `${activeTab === tabIndex ? ' tab-active' : ''}`"
                @click="handleSwitchTab(tabIndex)"
              >
                {{ tab.title }}
              </div>
            </template>
          </div>
        </div>
      </a-affix>

      <div class="result-panel">
        <menu-unfold-outlined
          v-if="collapsed"
          class="trigger"
          @click="() => (collapsed = !collapsed)"
        />
        <menu-fold-outlined v-else class="trigger" @click="() => (collapsed = !collapsed)" />
        <a-button size="small" type="danger" class="report-btn" @click="handleReport"
          >结果报告</a-button
        >
        <component :is="comId" :baseData="baseData" :collapsed="collapsed"></component>
      </div>
    </a-layout-content>
  </a-layout>
</template>

<script lang="ts" setup>
import { markRaw, shallowRef, watch, onMounted, reactive, ref } from 'vue';
import { LeftOutlined, MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
import { useRouter } from 'vue-router';
import logo from '/@/assets/icons/logo.svg';


import { useBarcode } from './hooks/useBarcode';
import { useTabs } from './hooks/useTabs';
import * as PhyloTreeApi from '/@/serve/api/phyloTree';

const router = useRouter();
const query = JSON.parse(JSON.stringify(router.currentRoute.value.query));
for (let key in query) Object.assign(query, { [key]: String(query[key]) });

const { taskId, barcodeId, sampleId, generation, barcodeName, primerList } = query;

const baseData = reactive({
  barcodeId,
  taskId,
  sampleId,
  barcodeName,
  primerList: primerList.split(','),
  generation,
});

const { activeTab, tabs, comId, handleSwitchTab } = useTabs(generation);

const { barcodeConfig } = useBarcode(baseData);

const collapsed = ref(true);

const handleBack = () => {
  router.go(-1);
};



const handleReport = () => {
  router.push(
    `/hiv/report?taskId=${taskId}&sampleId=${sampleId}&barcodeId=${barcodeId}&generation=${generation}&barcodeName=${barcodeName}`,
  );
};



const handleBackDashboard = () => {
  router.push('/dashboard');
};


</script>

<style lang="less" scoped>
@import '/@/assets/styles/views/result2.less';
</style>

useTabs.ts

import { reactive, ref, markRaw, shallowRef } from 'vue';

import NanoStats from '../../nanoStats/index.vue';
import HtvHtml from '../../htvHtml/index.vue';
import ResultAnalyse from '../../resultAnalyse/index.vue';
import ResultTable from '../../resultTable/index.vue';
import SeqOverview from '../../seqOverview/index.vue';
import Medaka from '../../medaka/index.vue';
import MinTree from '../../minTree/index.vue';
import EvolveTree from '../../evolveTree/index.vue';

export const useTabs = (generation: string) => {
  const tabs: Array<{ title: string; show: boolean; com: any }> = reactive([
    {
      title: '数据统计',
      show: generation == '5' ? true : false,
      com: markRaw(NanoStats),
    },
    {
      title: '分子溯源',
      show: generation == '6' ? true : false,
      com: markRaw(HtvHtml),
    },
    {
      title: '准种结果分析',
      show: generation == '5' ? true : false,
      com: markRaw(ResultAnalyse),
    },
    {
      title: '原始聚类结果表',
      show: generation == '5' ? true : false,
      com: markRaw(ResultTable),
    },
    {
      title: '多序列比对结果',
      show: generation == '5' ? true : false,
      com: markRaw(SeqOverview),
    },
    {
      title: '准种序列文本',
      show: generation == '5' ? true : false,
      com: markRaw(Medaka),
    },
    {
      title: '最小生成树',
      show: generation == '5' ? true : false,
      com: markRaw(MinTree),
    },
    {
      title: '进化树',
      show: generation == '5' ? true : false,
      com: markRaw(EvolveTree),
    },
  ]);

  const activeTab = ref(0);
  const comId = shallowRef(NanoStats);

  if (generation == '5') {
    activeTab.value = 0;
    comId.value = NanoStats;
  } else if (generation == '6') {
    activeTab.value = 1;
    comId.value = HtvHtml;
  }

  const handleSwitchTab = (tabIndex: number) => {
    comId.value = tabs[tabIndex].com;
    activeTab.value = tabIndex;
    document.body.scrollTop = document.documentElement.scrollTop = 0;
  };

  return {
    activeTab,
    comId,
    tabs,
    handleSwitchTab,
  };
};

你可能感兴趣的:(Vue,javascript,vue.js,前端)