使用 HTML Slot、HTML Template 和 Shadow DOM 从内容中提取文本

Avatar of Preethi
Preethi

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

书籍中的章节名称、演讲中的引用、文章中的关键词、报告中的统计数据——所有这些都是可以隔离并转化为内容重要性的高级摘要的内容类型。

例如,您是否看到 Business Insider 在进入内容之前提供了文章的关键要点?

这就是我们要做的事情,但尝试使用 HTML Slot、HTML Template 和 Shadow DOM 直接从文章中提取要点。

这三个标题规范通常用作 Web Components 的一部分——完全功能的自定义元素模块,旨在在网页中重复使用。

现在,我们的目标是文本提取,它不需要自定义元素,但它可以利用这三种技术。

有一个更基本的方法可以做到这一点。 例如,我们可以提取文本并在页面上显示提取的文本,使用一些基本的脚本,*而无需*使用 slot 和 template。 那么,如果我们可以使用更熟悉的东西,为什么要使用它们呢?

原因是**使用这些技术允许我们在 HTML 中为提取的文本预设标记代码(可选地,样式或脚本)**。 我们在继续本文时会看到这一点。

现在,作为我们将使用技术的非常淡化的定义,我会说

  • 模板是一组可以在页面中重复使用的标记。
  • Slot 是页面中指定元素的占位符。
  • Shadow DOM 是一个 DOM 树,在我们使用脚本添加它之前,它实际上不存在于页面上。

一旦我们开始编码,我们将更深入地了解它们。 现在,我们要做的是创建一篇包含文章关键点列表的文章。 而且,你可能已经猜到了,这些关键点是从文章文本中提取并汇集到关键点部分的。

查看 Pen
使用 HTML Slot 和 HTML Template 进行文本提取
by Preethi Sam (@rpsthecoder)
on CodePen.

关键点显示为一个列表,在要点之间有一个设计。 因此,让我们首先为该列表创建一个**模板**,并指定一个用于放置列表的位置。

<article><!-- Article content --></article>

<!-- Section where the extracted keypoints will be displayed -->
<section id='keyPointsSection'>
  <h2>Key Points:</h2>
  <ul><!-- Extracted key points will go in here --></ul>
</section>

<!-- Template for the key points list -->
<template id='keyPointsTemplate'>
  <li><slot name='keyPoints'></slot></li>
  <li style="text-align: center;">&#x2919;&mdash;&#x291a;</li>
</template>

我们得到的是一个语义化的 <section>,其中包含一个 <ul>,关键点列表将位于其中。 然后我们有一个 <template> 用于列表项,它包含两个 <li> 元素:一个带有 <slot> 占位符,用于来自文章的关键点,另一个带有居中的设计。

布局是任意的。 重要的是**在提取的关键点将要出现的位置放置一个 <slot>**。 <template> 内部的任何内容都不会在页面上呈现,直到我们使用脚本将其添加到页面中。

此外,<template> 内部的标记可以使用内联样式或由 <style> 包含的 CSS 进行设置样式

<template id='keyPointsTemplate'>
    <li><slot name='keyPoints'></slot></li>
    <li style="text-align: center;">&#x2919;&mdash;&#x291a;</li>
    <style>
        li{/* Some style */}
    </style>
</template>

有趣的部分! **让我们从文章中挑选关键点。** 注意 <template><slot>name 属性的值(keyPoints),因为我们需要它。

<article>
  <h1>Bears</h1>
  <p>Bears are carnivoran mammals of the family Ursidae. <span><span slot='keyPoints'>They are classified as caniforms, or doglike carnivorans</span></span>. Although only eight species of bears <!-- more content --> and partially in the Southern Hemisphere. <span><span slot='keyPoints'>Bears are found on the continents of North America, South America, Europe, and Asia</span></span>.<!-- more content --></p>
  <p>While the polar bear is mostly carnivorous, <!-- more content -->. Bears use shelters, such as caves and logs, as their dens; <span><span slot='keyPoints'>Most species occupy their dens during the winter for a long period of hibernation</span></span>, up to 100 days.</p>
  <!-- More paragraphs --> 
</article>

关键点被包装在一个 <span> 中,它带有 slot 属性值(“keyPoints”),与 <template><slot> 占位符的 name 相匹配。

还要注意,我在关键点之外添加了另一个 <span>**。

原因是插槽名称通常是唯一的,并且不会重复,因为一个 <slot> 使用一个插槽名称匹配一个元素。 如果有多个带有相同插槽名称的元素,<slot> 占位符将被所有这些元素连续替换,最后以最后一个元素作为占位符中的最终内容。

所以,如果我们将 <template> 中的单个 <slot> 与段落或整篇文章中所有具有相同 slot 属性值的 <span> 元素(我们的关键点)匹配,我们将最终只在段落或文章中最后一个关键点出现在 <slot> 的位置。

这不是我们需要的。 我们需要显示所有关键点。 因此,我们用外部 <span> 包装关键点,以便将每个单独的关键点与 <slot> 分别匹配。 通过查看脚本,这更加明显,所以让我们这样做。

const keyPointsTemplate = document.querySelector('#keyPointsTemplate').content;
const keyPointsSection = document.querySelector('#keyPointsSection > ul');
/* Loop through elements with 'slot' attribute */
document.querySelectorAll('[slot]').forEach((slot)=>{
  let span = slot.parentNode.cloneNode(true);
  span.attachShadow({  mode: 'closed' }).appendChild(keyPointsTemplate.cloneNode(true));
  keyPointsSection.appendChild(span);
});

首先,我们遍历每个带有 slot 属性的 <span> 并获取其父元素(外部 <span>)的副本。 请注意,如果愿意,我们也可以直接遍历外部 <span>,方法是为它们提供一个共同的 class 值。

然后,外部 <span> 副本被附加到一个阴影树 (span.attachShadow),该阴影树由模板内容的克隆组成 (keyPointsTemplate.cloneNode(true)).

这种“附加”导致模板列表项中的 <slot>(在阴影树中)吸收带有匹配插槽名称的内部 <span>,即我们的关键点。

然后,已插槽的关键点被添加到页面末尾的关键点部分 (keyPointsSection.appendChild(span))。

在循环过程中,所有关键点都会发生这种情况。

实际上就是这样。 我们已经从文章中获取了所有关键点,复制了它们,然后将副本放入列表模板中,以便所有关键点都组合在一起,提供文章的简明总结。

再次展示该演示

查看 Pen
使用 HTML Slot 和 HTML Template 进行文本提取
by Preethi Sam (@rpsthecoder)
on CodePen.

您如何看待这种技术? 这是否对长篇内容(如博客文章、新闻文章甚至维基百科条目)有用? 您能想到哪些其他用例?