阅读 92

Vanilla JavaScript进行页面内过滤搜索

如果你有一个包含大量信息的页面,让用户搜索他们可能要找的东西是一个好主意。我说的不是搜索数据库,甚至不是搜索JSON数据--我说的是在单个渲染的网页上搜索文本。用户已经可以使用内置的浏览器搜索,但我们可以通过提供我们自己的搜索功能来增强这一功能,在页面上进行过滤,使匹配结果更容易找到和阅读。

下面是我们要建立的一个现场演示。

CodePen嵌入回退

我在我的真实项目中也使用了这种技术:https://freestuff.dev/。

认识一下JavaScript!

好吧,你可能已经知道了JavaScript。JavaScript将处理这个旅程中的所有交互性。它将会...

  • 找到所有我们要搜索的内容。

  • 观察用户在搜索输入中输入的内容。

  • 过滤可搜索元素的innerText

  • 测试文本是否包括搜索词(.includes() 是这里的重头戏!),以及

  • 切换(父)元素的可见性,取决于它们是否包括搜索词。

好了,我们有了我们的要求!让我们开始工作。让我们开始工作吧。

基本标记

让我们假设我们有一个FAQ页面。每个问题都是一个 "卡片",有一个标题和内容。

<h1>FAQ Section</h1>

<div class="cards">
  <h3>Who are we</h3>
  <p>It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularized </p>
</div>

<div class="cards">
  <h3>What we do</h3>
  <p>It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularized </p>
</div>

<div class="cards">
  <h3>Why work here</h3>
  <p>It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularized</p>
</div>

<div class="cards">
  <h3>Learn more</h3>
  <p>Want to learn more about us?</p>
</div>复制代码

想象一下,这个页面上有很多问题。

为了为交互性做好准备,我们将有这一行CSS。这给了我们一个类,我们可以根据搜索的情况,在我们进入JavaScript的时候添加/删除。

.is-hidden { display: none; }复制代码

让我们添加一个搜索输入,当它被交互时,会有一个事件触发。

<label for="searchbox">Search</label>
<input 
  type="search" 
  oninput="liveSearch()" 
  id="searchbox" 
>复制代码

JavaScript的基线

这里是做其他事情的JavaScript!

function liveSearch() {
  // Locate the card elements
  let cards = document.querySelectorAll('.cards')
  // Locate the search input
  let search_query = document.getElementById("searchbox").value;
  // Loop through the cards
  for (var i = 0; i < cards.length; i++) {
    // If the text is within the card...
    if(cards[i].innerText.toLowerCase()
      // ...and the text matches the search query...
      .includes(search_query.toLowerCase())) {
        // ...remove the `.is-hidden` class.
        cards[i].classList.remove("is-hidden");
    } else {
      // Otherwise, add the class.
      cards[i].classList.add("is-hidden");
    }
  }
}复制代码

你也许可以逐行查看并推理出它在做什么。它找到所有的卡片和输入并保存对它们的引用。当一个搜索事件发生时,它循环浏览所有的卡片,确定文本是否在卡片内。如果卡片中的文本与搜索查询相匹配,.is-hidden 类就会被移除以显示卡片;如果不匹配,该类就在那里,卡片就会保持隐藏。

这里又是演示的链接。

添加一个延迟

为了确保我们的JavaScript不会运行_太多_(意味着它会拖慢页面),我们将在等待 "X "秒后才运行我们的liveSearch 函数。

<!-- Delete on Input event on this input -->
<label for="searchbox">Search</label>
<input type="search" id="searchbox">复制代码
// A little delay
let typingTimer;        
let typeInterval = 500; // Half a second
let searchInput = document.getElementById('searchbox');

searchInput.addEventListener('keyup', () => {
  clearTimeout(typingTimer);
  typingTimer = setTimeout(liveSearch, typeInterval);
});复制代码

模糊搜索怎么办?

比方说,你想通过用户可见的文本进行搜索。这个想法有点像模糊搜索,相关的关键词返回的结果与完全匹配的结果相同。这有助于扩大可能 "匹配 "搜索查询的卡片数量。

有两种方法可以做到这一点。第一种是使用一个隐藏的元素,比如span,它包含关键词。

<div class="cards">
  <h3>Who are we</h3>
  <p>It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularized</p>
  
    <!-- Put any keywords here -->
   <span class="is-hidden">secret</span> 
</div>复制代码

然后我们需要更新我们的liveSearch函数。我们将使用.innerText,而不是使用.textContent 来包括隐藏元素。请看更多关于innerText和textContent之间区别的细节。

 for (var i = 0; i < cards.length; i++) {
        if(cards[i].textContent.toLowerCase()
                .includes(search_query.toLowerCase())) {
            cards[i].classList.remove("is-hidden");
        } else {
            cards[i].classList.add("is-hidden");
        }
    }复制代码

试着在搜索框中输入 "secret",它应该会显示这张卡片,尽管 "secret "并没有显示在页面上。

CodePen嵌入回退

第二种方法是通过一个属性进行搜索。比方说,我们有一个图片库。我们可以把关键词直接放在图片的alt 属性上。尝试在下一个演示中输入 "小猫 "或 "人类"。这些查询是与图片alt 文本中包含的内容相匹配的。

CodePen嵌入回退

为了使其发挥作用,我们需要将innerText 改为getAttribute('alt') ,因为我们想通过alt 属性来查看页面上实际可见的内容。

for (var i = 0; i < cards.length; i++) {
  if(cards[i].getAttribute('alt').toLowerCase()
    .includes(search_query.toLowerCase())) {
      cards[i].classList.remove("is-hidden");
  } else {
    cards[i].classList.add("is-hidden");
  }
}复制代码

根据你的需要,你可以把你的关键词放在另一个属性中,或者是一个自定义的属性。

注意事项

同样,这不是一个通过查询数据库或其他数据源来工作的搜索技术。只有当你在该页面的DOM中拥有所有可搜索的内容,并且已经呈现出来时,它才能工作。

所以,是的,就是这样。只是要记住的东西。

收尾工作

显然,我非常喜欢这种技术,足以在生产网站上使用它。但你还可以如何使用这样的东西呢?正如我们所看到的,常见问题页面是一个明显的候选者,但任何需要过滤任何类型内容的情况都适合这种东西。甚至一个图片库也可以,使用隐藏的输入技巧来搜索图片的alt 标签内容。

不管是什么情况,我希望你觉得这很有帮助。我很惊讶,我们可以用几行虚无缥缈的JavaScript得到一个相当强大的搜索解决方案。


作者:前端小工
链接:https://juejin.cn/post/7023648636831694861


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐