绝美宋词:实时显示符合条件的完整宋词

  • 题目要求

请使用 Vue 或原生DOM ,完成 index.html 文件中的 TODO 部分。
1. 完成数据请求(数据来源 ./data.json),data.json 是宋词数据,poetry_content 表示词句,title 表示词牌名,author 表示词人。
2. 在输入框输入关键词时在 ul(class = suggestions)的元素中实时显示词牌名、词句、词人中包含关键词的完整词句(包含词牌名、词人)列表,当关键词为空或者匹配不到时 ul(class = suggestions)元素的子节点为空。完整词句的 DOM 结构按照如下规定显示:
<!-- 每一首完整词句用一个 li 包裹 -->

<li>
<span class="poet">词句</span>
<span class="title">词牌名 - 词人</span>
</li>


例:

<li>
<span class="poet">常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。
争渡,争渡,惊起一滩鸥鹭</span>
<span class="title">如梦令 - 李清照</span>
</li>


3. 高亮匹配到的所有词句中的关键词。即使用 <span class="highlight"></span> 标签
包裹所有关键词。例:(关键词:雨)

<li>
<span class="poet">寒蝉凄切,对长亭晚,骤<span class="highlight">雨
</span>初歇。都门帐饮无绪,方留恋处,兰舟催发。执手相看泪眼,竟无语凝噎。念去
去千里烟波,暮霭沉沉楚天阔。多情自古伤离别,更那堪冷落清秋节。今宵酒醒何处,杨柳
岸晓风残月。此去经年,应是良辰美景虚设。便纵有千种风情,更与何人说</span>
<span class="title"><span class="highlight">雨</span>霖铃 - 柳永
</span>
</li>


注意:本题要求的是实时显示,即输入完成的同时显示结果,非失去焦点显示

  • 目标分析

目标一:完成数据请求(数据来源 ./data.json)

使用fetch直接获取数据,并且对数据的格式进行处理。


        // 获取数据
        fetch("./data.json")
          .then((res) => res.json())
          .then((data) => {
            poetdata = data;
            // console.log(poetdata);
          });

目标二:通过input中的输入,进行实时搜索。完成input中输入的获取,以及需要实时进行搜索。

为了实时获取input中输入的数据,设置一个事件监听器。

input.addEventListener("input", function (e) {
          const keyword = e.target.value;
          suggestionsList.innerHTML = "";
          if (!keyword) {
            return;
          }

目标三:通过获取到的关键字在获取到的数据中进行搜索。

将用户输入的 keyword 转换为小写(lowerKeyword),确保搜索不区分大小写。将每个数据项的 poetry_contenttitleauthor 也转换为小写,与 lowerKeyword 进行比较。

使用 includes() 方法,检查关键词是否是目标字段的子串(无需完全匹配)。

const results = poetdata.filter((item) => {
            const lowerKeyword = keyword.toLowerCase();
            return (
              item.poetry_content.toLowerCase().includes(lowerKeyword) || // 检查词句
              item.title.toLowerCase().includes(lowerKeyword) || // 检查词牌名
              item.author.toLowerCase().includes(lowerKeyword) // 检查词人
            );
          });

目标四:将搜索到的数据按照一定的格式渲染到页面中。

results.forEach((item) => {
            const li = document.createElement("li");
            li.innerHTML = `
              <span class="poet">${item.poetry_content}</span>
              <span class="title">${item.title}-${item.author}</span> `;
            suggestionsList.appendChild(li);
          });

目标五:将结果中的关键字进行高亮处理。

将用户输入的 keyword 包裹在捕获组 () 中,生成正则表达式,并使用 gi 修饰符(全局匹配 + 不区分大小写)。

function highlight(text, keyword) {
          const regex = new RegExp(`(${keyword})`, "gi");
          return text.replace(regex, `<span class="highlight">$1</span>`);
        }

然后再输出代码中添加高亮。

  • 完整代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>绝美宋词</title>
    <link rel="stylesheet" href="css/style.css" />
    <script src="./js/axios.min.js"></script>
  </head>

  <body>
    <div class="container">
      <h1 style="text-align: center">输入关键字,找一首词</h1>
      <div class="search-form">
        <input
          type="text"
          id="searchInput"
          class="search"
          placeholder="词牌名 词句 词人"
        />
        <ul class="suggestions" id="suggestionsList">
          <li>
            <!-- 示例 -->
            <!-- <span class="poet"></span> -->
            <!-- <span class="title"></span> -->
          </li>
        </ul>
      </div>
    </div>
    <script>
      // TODO:待补充代码
      window.onload = function () {
        let poetdata = [];
        // 获取数据
        fetch("./data.json")
          .then((res) => res.json())
          .then((data) => {
            poetdata = data;
            // console.log(poetdata);
          });
        // 获取输入框
        const input = document.querySelector("#searchInput");
        const suggestionsList = document.querySelector("#suggestionsList");
        // input监听器
        input.addEventListener("input", function (e) {
          const keyword = e.target.value;
          suggestionsList.innerHTML = "";
          if (!keyword) {
            return;
          }
          // 数组一部分的浅拷贝
          const results = poetdata.filter((item) => {
            const lowerKeyword = keyword.toLowerCase();
            return (
              item.poetry_content.toLowerCase().includes(lowerKeyword) || // 检查词句
              item.title.toLowerCase().includes(lowerKeyword) || // 检查词牌名
              item.author.toLowerCase().includes(lowerKeyword) // 检查词人
            );
          });
          // console.log(results);
          results.forEach((item) => {
            const li = document.createElement("li");
            li.innerHTML = `
              <span class="poet">${highlight(
                item.poetry_content,
                keyword
              )}</span>
              <span class="title">${highlight(item.title, keyword)}-${highlight(
              item.author,
              keyword
            )}</span>
            `;
            suggestionsList.appendChild(li);
          });
        });
        // 高亮处理
        function highlight(text, keyword) {
          const regex = new RegExp(`(${keyword})`, "gi");
          return text.replace(regex, `<span class="highlight">$1</span>`);
        }
      };
    </script>
  </body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值