You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从AngularJS迁移到Vue,同一组件如何切换多套模板避免逻辑重复?

方案1:逻辑抽离 + 动态组件切换(最匹配AngularJS单controller多模板的使用习惯)

核心思路是把业务逻辑和视图层完全拆分,避免逻辑重复的同时解决模板臃肿问题:

  1. 抽离公共逻辑:
    如果是Vue3,把组件内所有公共状态(如items)、业务方法(如loadObject/viewType等)全部抽为独立的可复用组合式函数(composable):
// composables/useDataList.js
export default function useDataList() {
  const items = ref([])
  // 原有所有业务逻辑、接口请求、计算属性、交互方法都保留在此处
  const loadObject = (uid) => { /* 原有逻辑 */ }
  const viewType = (uid) => { /* 原有逻辑 */ }
  const expandOptions = (uid) => { /* 原有逻辑 */ }
  const analyze = (uid) => { /* 原有逻辑 */ }

  return { items, loadObject, viewType, expandOptions, analyze }
}

如果是Vue2,把上述公共逻辑抽为mixin即可。
2. 编写独立视图组件:
每个视图只写对应模板,逻辑直接复用上述抽离的公共代码,无需重复编写:

<!-- components/TableView.vue -->
<template>
  <table>
    <tr><td>Name</td><td>Type</td><td>Actions</td></tr>
    <tr v-for="item in items" :key="item.Uid">
      <td @click="loadObject(item.Uid)">{{item.Name}}</td>
      <td @click="viewType(item.Uid)">{{item.Type}}</td>
      <td>
        <span @click="expandOptions(item.Uid)">Expand</span>
        <span @click="analyze(item.Uid)"></span>
      </td>
    </tr>
  </table>
</template>
<script setup>
import useDataList from '@/composables/useDataList'
const { items, loadObject, viewType, expandOptions, analyze } = useDataList()
</script>

按同样方式编写ListView.vue,只替换模板部分即可。
3. 父组件通过动态组件实现一键切换:

<template>
  <div>
    <!-- 视图切换按钮 -->
    <button @click="toggleView">切换视图</button>
    <!-- 动态渲染当前选中的视图组件 -->
    <component :is="currentView" />
  </div>
</template>
<script setup>
import { ref } from 'vue'
import TableView from '@/components/TableView.vue'
import ListView from '@/components/ListView.vue'

const currentView = ref('TableView')
const toggleView = () => {
  currentView.value = currentView.value === 'TableView' ? 'ListView' : 'TableView'
}
</script>

方案2:模板片段拆分(不想拆分组件的轻量优化方案)

如果不想调整现有逻辑结构,只需要解决模板臃肿问题,可以把两个视图的代码单独抽为独立的模板片段文件,在主组件中引入即可:

  1. 新建table-view.html和list-view.html,分别存放对应视图的模板代码
  2. 主组件模板通过构建工具的引入能力加载片段(Vite可使用vite-plugin-html-include,Vue CLI可使用html-loader):
<template>
  <div>
    <div v-if="showTable">
      <!-- @include ./table-view.html -->
    </div>
    <div v-if="showList">
      <!-- @include ./list-view.html -->
    </div>
  </div>
</template>
<!-- 原有script逻辑完全不用改动 -->

方案3:作用域插槽封装(适合后续需扩展更多视图的场景)

如果后续还会新增卡片视图、缩略图视图等更多展示形式,可以把所有业务逻辑封装为容器组件,通过作用域插槽向外暴露状态和方法,完全自定义视图:

<!-- components/DataListContainer.vue -->
<template>
  <!-- 把所有状态、方法通过插槽传给父组件 -->
  <slot :items="items" :loadObject="loadObject" :viewType="viewType" :expandOptions="expandOptions" :analyze="analyze" />
</template>
<script setup>
// 原有所有业务逻辑全部放在此处,无需改动
</script>

使用时直接在插槽内切换视图即可:

<template>
  <DataListContainer v-slot="slotProps">
    <!-- 表格视图 -->
    <table v-if="showTable">
      <tr v-for="item in slotProps.items" :key="item.Uid">
        <td @click="slotProps.loadObject(item.Uid)">{{item.Name}}</td>
        <!-- 剩余表格代码 -->
      </tr>
    </table>
    <!-- 列表视图 -->
    <div v-else>
      <!-- 列表代码 -->
    </div>
  </DataListContainer>
</template>

内容的提问来源于stack exchange,提问作者Gotts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 00:39:03