【问题标题】:Switch template on same component in Vue在Vue中的同一组件上切换模板
【发布时间】:2021-12-01 03:15:16
【问题描述】:

我正在从 angularjs 迁移到 Vue。 Angularjs 很好,因为单个控制器可以应用于不同的模板。 因此,使用同一个控制器,我可以通过 list.html 模板或 table.html 模板显示它,并轻松地在相同数据的列表视图或表格视图之间切换。

在 vue 中我需要创建一个使用固定模板的组件。该组件可能有很多业务逻辑,但我希望能够在列表视图或表格视图之间轻松切换。 用 Vue 实现这一目标的正确方法是什么?

谢谢

更新

只是添加一些细节。我目前正在做的只是将两个视图都包含在一个模板中,并带有一些逻辑来确定要显示两者中的哪一个。 这使它更简单,因为我不必复制所有逻辑或方法,我将它们分成两个组件。同时它非常混乱。 这是我正在做的一个粗略示例:

<template>
<div>
<div v-if="showTable">
<table>
<tr><td>Name</td><td>Type</td><td>Actions</td></tr>
<tr v-for="item in items">
<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>
</div>

<div v-if="showList">
<div v-for="item in items">
  <div class="list" @click="loadObject(item.Uid)>{{item.Name}}</div>
  <div@click="viewType(item.Uid)>{{item.Type}}</div>
  <div><span @click="expandOptions(item.Uid)">Expand</span><span @click="analyze(item.Uid)"></span></div>
</div>
</div>
</div>
</template>

这是我需要的高度简化版本,最终有很多逻辑和方法。通过这种方法,我现在可以在一个组件中拥有所有这些方法和逻辑。但是管理上面的模板就变得很乱了。

有什么建议吗?

【问题讨论】:

    标签: angularjs vue.js vue-component


    【解决方案1】:

    您要查找的是使用is 绑定加载的dynamic component,格式为:

    <component :is="componentView" />
    

    ...其中componentView 可以在data 或返回Vue 组件的计算道具中。这允许您在 &lt;component&gt; 标记中指定要加载的组件。本质上,每个 Vue 组件只有一个模板,但你可以随时在不同的组件之间切换。

    这是一个概念验证示例:

    const listComponent = Vue.component('list-component', {
      template: '#list-component-template',
      props: {
        items: {
          type: Array,
          required: true
        }
      }
    });
    
    const tableComponent = Vue.component('table-component', {
      template: '#table-component-template',
      props: {
        items: {
          type: Array,
          required: true
        }
      }
    });
    
    new Vue({
      el: '#app',
      data: {
        view: 'list',
        items: ['Lorem', 'Ipsum', 'Dolor', 'Sit', 'Amet']
      },
      methods: {
        switchView: function() {
          if (this.view === 'list') {
            this.view = 'table';
          } else {
            this.view = 'list';
          }
        }
      },
      computed: {
        componentView: function() {
          if (this.view === 'list') {
            return listComponent;
          } else {
            return tableComponent;
          }
        }
      }
    })
    .grid {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
    }
    
    .grid .cell {
      border: 1px solid #000;
      padding: 1rem;
      margin: 1rem;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <button type="button" @click="switchView">Switch view</button>
      <component :is="componentView" :items="items" />
    </div>
    
    <script type="text/x-template" id="list-component-template">
      <ul>
        <li v-for="(item, i) in items" :key="i">
          {{ item }}
        </li>
      </ul>
    </script>
    
    <script type="text/x-template" id="table-component-template">
      <div class="grid">
        <div v-for="(item, i) in items" :key="i" class="cell" >
          {{ item }}
        </div>
      </div>
    </script>

    【讨论】:

    • 感谢您的信息。动态组件解决了如何在组件之间轻松切换的问题,但它并不能帮助我解决主要问题 - 当唯一的区别在于显示时不必复制所有逻辑(但太复杂而无法使用 css 处理)。 Vue中没有其他方法可以做到吗?
    • @Gotts 为什么担心代码重复?如果您在动态组件中使用插槽,那么您可以简单地将内容交织到其中而无需重复大量块。
    • 这可能是我误解了如何在这里使用插槽。但是在每个视图中都有很多功能和逻辑必须发生。如何在不复制组件中的逻辑的情况下让每个视图组件轻松使用所有这些功能。我意识到我可以从视图组件中发出事件并触发父级中的方法,但这将是很多工作(与它在角度工作的方式相比) - 所以希望有其他解决方案
    • 我为我的问题添加了更新以更清楚
    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 2016-08-20
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 2020-07-20
    • 2019-05-02
    相关资源
    最近更新 更多