目录
Vue 的内置 元素
按钮还是链接?
有序列表还是无序列表?
现在我们正在控制元素
扩展思路,灵活的卡片系统
组件中的组件的力量
首页 web前端 css教程 在VUE中动态切换到另一个HTML元素

在VUE中动态切换到另一个HTML元素

Mar 27, 2025 pm 12:01 PM

Dynamically Switching From One HTML Element to Another in Vue

最近一位朋友问我,如何在 Vue 模板块中动态地将一个 HTML 元素更改为另一个元素。例如,根据某些条件将 <div> 元素切换为 <code><p></p> 元素。关键是如何做到这一点,而无需依赖一系列 v-ifv-else 代码。起初我并没有太在意,因为我看不出这么做的强烈理由;这种情况并不常见。然而,同一天晚些时候,他又联系了我,告诉我他学会了如何更改元素类型。他兴奋地指出,Vue 有一个内置组件,可以作为动态元素,正是他所需要的。

这个小功能可以使模板代码保持简洁整齐。它可以减少 v-ifv-else 的冗余代码,从而使代码更易于理解和维护。这允许我们使用方法或计算属性在脚本块中创建编写良好且更复杂的条件。这些东西应该放在脚本中,而不是模板块中。

我写这篇文章的主要原因是,在我们工作的设计系统中,有多处使用了这个功能。诚然,这不是一个很大的功能,而且在文档中几乎没有提到,至少据我所知是这样。然而,它有潜力帮助渲染组件中的特定 HTML 元素。

Vue 的内置 <component></component> 元素

Vue 中有几个功能可以轻松地动态更改视图。其中一个功能是内置的 <component></component> 元素,它允许组件动态切换。在 Vue 2 和 Vue 3 的文档中,都有一小段关于使用此元素与 HTML 元素的说明;这就是我们现在要探讨的部分。

其理念是利用 <component></component> 元素的这一特性来替换性质上较为相似,但功能、语义或视觉效果不同的常用 HTML 元素。以下基本示例将展示此元素在保持 Vue 组件简洁整齐方面的潜力。

按钮还是链接?

按钮和链接经常互换使用,但它们的功能、语义甚至视觉效果都存在很大差异。一般来说,按钮(<button></button>)用于当前视图中的内部操作,并与 JavaScript 代码绑定。另一方面,链接(<a></a>)旨在指向另一个资源,无论是主机服务器上的资源还是外部资源;大多数情况下是网页。单页应用程序往往更依赖按钮而不是链接,但两者都是需要的。

链接在视觉上经常被设计成按钮的样子,就像 Bootstrap 的 .btn 类创建的按钮外观一样。考虑到这一点,我们可以轻松创建一个组件,根据单个 prop 在这两个元素之间切换。默认情况下,该组件将是一个按钮,但如果应用了 https://www.php.cn/link/ed2ddd0dcd323046d0f9a51e5cc51c60 prop,它将呈现为链接。

这是模板中的 <component></component>

<component :https: :is="element"><slot></slot></component>
登录后复制

此绑定属性指向名为 element 的计算属性,而绑定 https://www.php.cn/link/ed2ddd0dcd323046d0f9a51e5cc51c60 属性使用恰当命名的 https://www.php.cn/link/ed2ddd0dcd323046d0f9a51e5cc51c60 prop。这利用了 Vue 的正常行为,即如果 prop 没有值,则绑定属性不会出现在渲染的 HTML 元素中。无论最终元素是按钮还是链接,slot 都提供内部内容。

计算属性很简单:

element() {
  return this.https://www.php.cn/link/ed2ddd0dcd323046d0f9a51e5cc51c60 ? 'a' : 'button';
}
登录后复制

如果有 https://www.php.cn/link/ed2ddd0dcd323046d0f9a51e5cc51c60 prop,则应用 <a></a> 元素;否则我们得到一个 <button></button>

<my-button>this is a button</my-button>
<my-button https:>this is a link</my-button>
登录后复制

HTML 呈现如下:

<button>this is a button</button>
<a https:>this is a link</a>
登录后复制

在这种情况下,人们可能会期望这两个元素在视觉上相似,但出于语义和可访问性的需要,它们显然是不同的。也就是说,这两个输出的元素不必具有相同的样式。您可以使用带有选择器 div.my-button 的元素在样式块中,或者创建一个根据元素变化的动态类。

总的目标是通过允许一个组件根据需要呈现为两个不同的 HTML 元素来简化事情——无需 v-ifv-else

有序列表还是无序列表?

与上面的按钮示例类似,我们可以创建一个输出不同列表元素的组件。由于无序列表和有序列表都使用相同的列表项 (<li>) 元素作为子元素,因此这很容易实现;我们只需交换 <ul></ul><ol></ol>。即使我们想要选择使用描述列表 <dl></dl>,这也很容易实现,因为内容只是一个可以接受 <dt></dt>/<dd></dd> 组合的 slot。模板代码与按钮示例非常相似:

<component :is="element"><slot>No list items!</slot></component>
登录后复制

请注意 slot 元素内的默认内容,我稍后会讲到。

有一个 prop 用于指定要使用的列表类型,默认为 ul

props: {
  listType: {
    type: String,
    default: 'ul'
  }
}
登录后复制

同样,还有一个名为 element 的计算属性:

element() {
  if (this.$slots.default) {
    return this.listType;
  } else {
    return 'div';
  }
}
登录后复制

在这种情况下,我们正在测试默认 slot 是否存在,这意味着它有内容要渲染。如果存在,则使用通过 listType prop 传递的列表类型。否则,元素将成为 <div>,这将显示 slot 元素内的“No list items!”消息。这样,如果没有列表项,则 HTML 不会呈现为只有一个项目声明没有项目的列表。不过,这取决于你,但考虑一下没有明显有效项目的列表的语义是很好的。另一件需要考虑的事情是,辅助工具可能会混淆,认为这是一个只有一个项目声明没有项目的列表。就像上面的按钮示例一样,您也可以对每个列表进行不同的样式设置。这可以基于选择器来定位带有类名 <code>ul.my-list 的元素。另一种选择是根据所选元素动态更改类名。

此示例遵循类似 BEM 的类命名结构:

<component :class="`my-list ${element}`" :is="element"><slot>No list items!</slot></component>
登录后复制

用法与之前的按钮示例一样简单:

<my-list><li>list item 1</li></my-list>
<my-list list-type="ol"><li>list item 1</li></my-list>
<my-list list-type="dl"><dt>Item 1</dt>
<dd>This is item one.</dd></my-list>
<my-list></my-list>
登录后复制

每个实例都呈现指定的列表元素。但是,最后一个实例会生成一个

,声明没有列表项,因为,嗯,没有列表要显示!有人可能会想,当它可以只是简单的 HTML 时,为什么要创建一个在不同列表类型之间切换的组件。虽然出于样式和可维护性原因,将列表包含在组件中可能有很多好处,但也可以考虑其他原因。例如,如果某些形式的功能与不同的列表类型绑定在一起?也许可以考虑对列表进行排序,切换到 <ol></ol> 以显示排序顺序,然后在完成时切换回来?

现在我们正在控制元素

即使这两个示例本质上是更改根元素组件,也要考虑更深入地进入组件。例如,标题可能需要根据某些条件从 <h1></h1> 更改为 <h3></h3>


如果您发现自己必须使用三元运算符来控制超过几个属性的内容,我建议您坚持使用 v-if。编写更多代码来处理属性、类和属性只会使代码比 v-if 更复杂。在这些情况下,从长远来看,v-if 会使代码更简单,而更简单的代码更易于阅读和维护。

在创建组件时,如果有一个简单的 v-if 来在元素之间切换,请考虑 Vue 主要功能的这个小方面。

扩展思路,灵活的卡片系统

考虑一下我们到目前为止所涵盖的所有内容,并将其应用于灵活的卡片组件中。此卡片组件示例允许将三种不同类型的卡片放置在文章布局的特定部分:

    <li> 英雄卡:预计这将用于页面顶部,并比其他卡片更引人注目。 <li> 号召性用语卡:用作文章之前或文章内的一系列用户操作。 <li> 信息卡:用于摘录。

将这些视为遵循设计系统,并且组件控制 HTML 以实现语义和样式。

在上面的示例中,您可以看到顶部的英雄卡,接下来是一系列号召性用语卡,然后——向下滚动一点——您会在右侧看到信息卡。

以下是卡片组件的模板代码:

<component :class="`card ${type}`" :is="elements('root')">
  <component :style="bg()" :is="elements('header')">
    <slot name="header"></slot>
  </component>
  <div>
    <slot name="content"></slot>
  </div>
  <component :is="elements('footer')">
    <slot name="footer"></slot>
  </component>
</component>
登录后复制

卡片中有三个“component”元素。每个元素代表卡片内的特定元素,但将根据卡片类型而改变。每个组件都使用一个参数调用 elements() 方法,该参数标识调用卡片的哪个部分。

elements() 方法是:

elements(which) {
  const tags = {
    hero: { root: 'section', header: 'h1', footer: 'date' },
    cta: { root: 'section', header: 'h2', footer: 'div' },
    info: { root: 'aside', header: 'h3', footer: 'small' }
  }
  return tags[this.type][which];
}
登录后复制

可能有很多方法可以处理这个问题,但是你必须朝着适合你组件需求的方向前进。在这种情况下,有一个对象跟踪每个卡片类型中每个部分的 HTML 元素标签。然后,该方法根据当前卡片类型和传入的参数返回所需的 HTML 元素。

对于样式,我在卡片的根元素上插入了一个类,该类基于卡片的类型。这使得根据要求创建每种类型的 CSS 变得非常容易。您也可以根据 HTML 元素本身创建 CSS,但我更喜欢类。将来对卡片组件的更改可能会更改 HTML 结构,并且不太可能更改创建类的逻辑。

卡片还支持英雄卡的标题上的背景图像。这是通过在标题元素上放置一个简单的计算属性 bg 来完成的。这是计算属性:

bg() {
  return this.background ? `background-image: url(${this.background})` : null;
}
登录后复制

如果在 background prop 中提供图像 URL,则计算属性将返回一个字符串,用于内联样式,该样式将图像应用为背景图像。一个相当简单的解决方案,可以很容易地使其更强大。例如,它可以支持自定义颜色、渐变或默认颜色(如果没有提供图像)。此示例没有涉及大量可能性,因为每种卡片类型都可能拥有自己的可选 prop 供开发人员利用。

这是此演示中的英雄卡:

<custom-card background="https://picsum.photos/id/237/800/200" type="hero">
  <template v-slot:header>Article Title</template>
  <template v-slot:content>Lorem ipsum...</template>
  <template v-slot:footer>January 1, 2011</template>
</custom-card>
登录后复制

您会看到卡片的每个部分都有自己的内容槽。而且,为了简单起见,文本是槽中唯一预期的东西。卡片组件根据卡片类型处理所需的 HTML 元素。让组件只期望文本使得使用组件相当简单。它取代了需要做出关于 HTML 结构的决策,从而简化了卡片的实现。

为了进行比较,以下是演示中使用的其他两种类型:

<custom-card type="cta">
  <template v-slot:header>CTA Title One</template>
  <template v-slot:content>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</template>
  <template v-slot:footer>footer</template>
</custom-card>
<custom-card type="info">
  <template v-slot:header>Here's a Quote</template>
  <template v-slot:content>“Maecenas ... quis.”</template>
  <template v-slot:footer>who said it</template>
</custom-card>
登录后复制

同样,请注意每个槽只期望文本,因为每种卡片类型都会根据 elements() 方法的定义生成自己的 HTML 元素。如果将来认为应该使用不同的 HTML 元素,则只需更新组件即可。构建辅助功能特性是另一个潜在的未来更新。甚至可以根据卡片类型扩展交互功能。

组件中的组件的力量

Vue 组件中奇怪命名的 <component></component> 元素原本是为一件事设计的,但正如经常发生的那样,它有一个小的副作用,使其在其他方面非常有用。<component></component> 元素旨在根据需要动态切换另一个组件内的 Vue 组件。对此的一个基本想法可能是一个选项卡系统,用于在充当页面的组件之间切换;这实际上在 Vue 文档中有所说明。但它支持对 HTML 元素执行相同的操作。

这是一个朋友分享的新技术示例,它已成为我使用过的 Vue 功能中一个令人惊讶的有用工具。我希望这篇文章能够将有关此小功能的想法和信息传递给您,让您探索如何在您自己的 Vue 项目中利用它。

以上是在VUE中动态切换到另一个HTML元素的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1676
14
CakePHP 教程
1429
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
静态表单提供商的比较 静态表单提供商的比较 Apr 16, 2025 am 11:20 AM

让我们尝试在这里造成一个术语:“静态表单提供商”。你带上html

使Sass更快的概念证明 使Sass更快的概念证明 Apr 16, 2025 am 10:38 AM

在一个新项目开始时,Sass汇编发生在眼睛的眨眼中。感觉很棒,尤其是当它与browsersync配对时,它重新加载

每周平台新闻:HTML加载属性,主要的ARIA规格以及从iframe转移到Shadow dom 每周平台新闻:HTML加载属性,主要的ARIA规格以及从iframe转移到Shadow dom Apr 17, 2025 am 10:55 AM

在本周的平台新闻综述中,Chrome引入了一个用于加载的新属性,Web开发人员的可访问性规范以及BBC Move

带有HTML对话框元素的一些动手 带有HTML对话框元素的一些动手 Apr 16, 2025 am 11:33 AM

这是我第一次查看HTML元素。我已经意识到了一段时间,但是尚未将其旋转。它很酷,

纸张形式 纸张形式 Apr 16, 2025 am 11:24 AM

购买或建造是技术的经典辩论。自己构建东西可能会感觉更便宜,因为您的信用卡账单上没有订单项,但是

'订阅播客”链接应在哪里? '订阅播客”链接应在哪里? Apr 16, 2025 pm 12:04 PM

有一段时间,iTunes是播客中的大狗,因此,如果您将“订阅播客”链接到喜欢:

托管您自己的非JavaScript分析的选项 托管您自己的非JavaScript分析的选项 Apr 15, 2025 am 11:09 AM

有很多分析平台可帮助您跟踪网站上的访问者和使用数据。也许最著名的是Google Analytics(广泛使用)

See all articles