发布于 2026-01-06 0 阅读
0

Vue动态组件在数据列表方面的魔力

Vue动态组件在数据列表方面的魔力

在drewtown.dev上查看这篇文章及其他类似文章。

Vue 的动态组件是 Vue 最被低估的强大功能之一。它们允许开发者通过变量或计算属性指定在运行时加载的子组件,从而减少展示逻辑和代码冗余。

<component :is="activeTabComponent" />

常见的例子是选项卡组件,它会根据当前选中的选项卡动态地引入相应的子组件。这是一种很棒的模式用法,但我更想看看一些不同的用法。

我想了解如何处理包含各种项目和数据类型的对象。对于这些项目,您希望以列表形式显示,并呈现格式良好的输出,这些输出可以是日期、项目数组、长文本,甚至仅仅是一个名称。

让我们来看一下这个对象,看看我们正在处理什么类型的数据。

const person = {  
  firstName: "John",  
  lastName: "Doe",  
  birthdate: "1986-06-22T00:00:00Z",  
  anniversary: "2005-10-09T00:00:00Z",  
  activities: ["Skiing", "Hiking", "Cycling", "Drinking Beer"],  
  about: "John talking about himself. It goes on and on forever...[snip]",      
  metadata: {
    lastUpdateUTC: "2019-06-29T15:14:00Z",
    lastUpdatedBy: "admin"
  }
}

这只是一个小例子,但你可以想象一下,如果有 20、30 甚至 40 个字段,每个字段有 5-10 种不同类型的数据,会是什么情况。

使用HTML模板

你可以把所有需要的东西都放到HTML模板里。它简单易用,而且效果很好。

<li><span class="item-title">Birthday</span> {{formatDate(person.birthday)}}</li>

不过,这种方法也有一些缺点。

首先,如果你的数据集非常庞大,而且你的展示元素足够复杂,那么在处理数据集的过程中,你最终会得到大量的 HTML 代码。我们拥有 Vue 的强大功能,但实际上我们却把它当作一种简单的模板语言来使用。大量的 HTML 代码会让组件难以理解,更新起来更是难上加难。更改一个类名就变成了查找替换,而修改实际的 HTML 结构简直是噩梦。

其次,你的 HTML 模板中现在必须包含格式化逻辑。随意添加formatDate方法(可能还带有参数)并不是好的做法。

对于“关于”字段,我们可能希望将超过一定长度的文本隐藏在“显示更多/更少”的切换按钮后面。这需要在本组件中处理状态,而最好由子组件来处理。

或许我们应该把所有这些逻辑都移到这些项目的子组件里。🤔

将所有逻辑移至子组件

既然我们已经确定对象的子组件包含足够复杂的逻辑,可能需要自己的状态、格式化或外部库,那么我们将把所有这些逻辑移到子组件中,例如details-datedetails-textdetails-list

<li><span class="item-title">Birthday</span> <details-text :value="person.firstName + ' ' + person.lastName" /></li>
<li><span class="item-title">Birthday</span> <details-date :value="person.birthday" /></li>
<li><span class="item-title">About</span> <details-text-expander :value="person.about" /></li>
<li><span class="item-title">Activities</span> <details-list :value="person.activities" /></li>

这样好多了!至少现在我们不会再让父级组件接收到每个元素的格式和显示属性等细节信息了。父级组件不应该关心日期是如何实现的,也不应该关心超长文本字段是否展开。这些都是子级组件的职责,应该封装起来。

不过我们还可以做得更好。仍然存在HTML代码重复的问题。

引入动态组件

让我们把数据转换成一种略有不同的格式。

  // Make sure you import and register all of the components you specify here
  computed: {
    items() {
      return [
          { name: "Name", value: `${this.person.firstName} ${this.person.lastName}`, component: "DetailsText" },
          { name: "Birthday", value: this.person.birthday, component: "DetailsDate" },
          { name: "About", value: this.person.about, component: "DetailsTextExpander" },
          { name: "Activities", value: this.person.activities, component: "DetailsList" },
      ];
    }
  }

我们的计算属性将返回一个对象数组。每个对象将包含名称、要传递给子组件的值以及要使用的子组件。

无论列表中有多少项,我们的完整 HTML 代码现在看起来都如下所示。

<li v-for="item in items" :key="item.name">
  <span class="item-title">{{item.name}}</span>
  <component :is="item.component" :value="item.value" />
</li>

我们遍历 items 数组中的所有元素,设置标题,并使用对象中指定的组件以及指定的值创建动态子组件。这种方法简洁高效,使更新显示内容变得轻而易举,并且允许您将所有有关要显示内容的详细信息保存在一个易于理解的计算属性中。

文章来源:https://dev.to/drewtownchi/the-magic-of-vue-s-dynamic-components-for-lists-of-data-5j8