文章目录
- 思路分析
- 具体实现
- 源码
不知道大家平常有没有自己空闲的时候写一些小demo的习惯呢?我个人觉得,在空闲的时候时不时写一个小功能,日积月累,当你以后遇到需要使用的时候,就可以直接拿来使用,当然了。业务的需求多变的,多少可能会改一点,不过也一定比从没写过开始写要快得多,本文就介绍一个比较有意思但是也很简单的案例–搜索关键字高亮
思路分析
- 当我们需要对关键词高亮的时候,先决条件是什么呢?毫无疑问,是我们需要对数据进行匹配,找到和关键词相匹配的内容
- 而找到这个内容之后,如何进行高亮呢?在页面中,我们需要对文字进行颜色改变或者其他样式设置的时候,是不是都需要给其包裹一个标签,这里也不例外,假设我们有一段数据是:123456,我们搜索的是 23,我们需要对这段文本改造为
1<span>23</span>456
,而后我们对这个 span 标签设置不同的颜色或者其他样式,在显示到页面上,是不是就可以了呢
具体实现
-
我们先看一下样式布局吧,这个样式布局非常简单,我就只展示显示的效果了,可以自己实现,或者在文章末尾直接复制源码,如图:
-
现在就是根据我们的分析来具体实现,准备的数据如下:
const data = ['我们等待着戈多,在等待的过程中发现戈多就是等待本身。--王希明','我们登上并非我们所选择的舞台,演出并非我们所选择的剧本。--Enchiridion','慢慢来,谁还没有一个努力的过程。--网易云音乐','上了陆地的鱼就不能再叫做鱼了。--三体:黑暗森林','历史的发展是不以人的意志为转移的。--毛泽东','人生天地间,忽如远行客。--古诗十九首','甲之蜜糖,乙之砒霜。--曼陀罗','回眸一笑百媚生,六宫粉黛无颜色。--长恨歌','天之涯,地之角,知交半零落,一壶浊酒尽余欢,今宵别梦寒。--送别','荒诞也好,愚笨也好,总会过去的。--一瞬的光和永远' ]
-
获取 dom,绑定事件如下:
const contentList = document.querySelector('.content-list') const inp = document.querySelector('.inp')form.addEventListener('submit', function (e) {e.preventDefault()render(data, inp.value) })
-
是不是发现了藏在这个事件里面的 render 函数呢?我们的核心就是实现这个函数,这个函数接收两个参数,一个是数据列表,一个是关键词,于是我们可以根据写出 render 函数的函数签名,如下:
function render(list, keyword){}
-
然后我们就应该来思考一下,前置条件,在这里,我们明显只有一个条件,那就是有没有关键词,有的话如何,没有的话又如何,首先我们第一步是不是要通过这个有没有关键词进行筛选数据呢?
function render(list, keyword){let newList = listif (keyword) {// 根据关键词输入的筛选数据newList = list.filter(item => item.includes(keyword))} }
-
在筛选数据的时候,就可以感觉到如果需要往下执行,我们还缺少一个条件,关键词匹配的条件,关键词匹配,我们可以想到什么?是不是正则表达式呢?所以我们还需要定义条件,当有关键词的时候,需要创建一个正则表达式,如下:
function render(list, keyword) {let newList = listlet regif (keyword) {newList = list.filter(item => item.includes(keyword))// 创建正则表达式reg = new RegExp(keyword, 'gi')}}
-
而有了这个筛选后的数据和正则,我们就可以进行真正的渲染了,这个渲染可以手动通过方法创建元素,也可以直接设置 html 字符串,我这里方便演示,就直接使用设置 html 字符串了,如下:
function render(list, keyword) {let newList = listlet regif (keyword) {newList = list.filter(item => item.includes(keyword))// 创建正则表达式reg = new RegExp(keyword, 'gi')}contentList.innerHTML = newList.map(item=>{// 设置默认值let content = item// 如果存在有正则表达式存在则表示需要对内容进行关键词匹配if (reg) {// 将匹配的关键词通过 replace 方法进行替换-并重新赋值给 contentcontent = item.replace(reg, `<span class="highlight">${keyword}</span>`)}// 返回组装的 html 字符串return `<div class="item-box"><p class="item-content">${content}</p></div>`}).join('') }
-
这里我们给高亮的 span 的类名定义为 highlight,所以响应的我们需要再 css 文件中定义这样的一个高亮关键词样式,如下:
/* 设置关键词样式 */ .item-content .highlight {color: #ff4757;font-weight: bold; }
-
我们最后来看一下展示的效果,如图:
-
这个数据的筛选,是不是需要,可以自己根据自己的需求来设计,这个案例整体是不是还是比较简单呢
源码
-
index.html
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./index.css"> </head><body><div class="container"><!-- 搜索 --><div class="search-box"><form id="form"><input class="inp" autocomplete="off" spellcheck="false" type="text" id="keyword" placeholder="请输入关键字"><button type="submit" style="display: none;"></button></form></div><!-- 内容列表 --><div class="content-list"></div></div><script src="./index.js"></script> </body></html>
-
index.css
* {margin: 0;padding: 0;box-sizing: border-box; }.container {width: 100vw;height: 100vh;overflow: hidden;padding: 50px; }.search-box {width: 300px;height: 35px;border: 1px solid #999;border-radius: 3px;margin-bottom: 20px; }.search-box input {all: unset;padding: 0 5px;height: 35px;font-size: 14px; }input::placeholder {color: #ccc; }.content-list {width: 720px;flex: 1;overflow: hidden auto; }.item-box {margin-bottom: 10px; }.item-content {color: #130f40;font-size: 16px; }/* 设置关键词样式 */ .item-content .highlight {color: #ff4757;font-weight: bold; }
-
index.js
const data = ['我们等待着戈多,在等待的过程中发现戈多就是等待本身。--王希明','我们登上并非我们所选择的舞台,演出并非我们所选择的剧本。--Enchiridion','慢慢来,谁还没有一个努力的过程。--网易云音乐','上了陆地的鱼就不能再叫做鱼了。--三体:黑暗森林','历史的发展是不以人的意志为转移的。--毛泽东','人生天地间,忽如远行客。--古诗十九首','甲之蜜糖,乙之砒霜。--曼陀罗','回眸一笑百媚生,六宫粉黛无颜色。--长恨歌','天之涯,地之角,知交半零落,一壶浊酒尽余欢,今宵别梦寒。--送别','荒诞也好,愚笨也好,总会过去的。--一瞬的光和永远' ]const contentList = document.querySelector('.content-list') const inp = document.querySelector('.inp')form.addEventListener('submit', function (e) {e.preventDefault()render(data, inp.value) })function render(list, keyword) {let newList = listlet regif (keyword) {newList = list.filter(item => item.includes(keyword))reg = new RegExp(keyword, 'gi')}contentList.innerHTML = newList.map(item => {let content = itemif (reg) {content = item.replace(reg, `<span class="highlight">${keyword}</span>`)}return `<div class="item-box"><p class="item-content">${content}</p></div>`}).join('') }render(data, '')