搜索关键字高亮

不知道大家平常有没有自己空闲的时候写一些小demo的习惯呢?我个人觉得,在空闲的时候时不时写一个小功能,日积月累,当你以后遇到需要使用的时候,就可以直接拿来使用,当然了。业务的需求多变的,多少可能会改一点,不过也一定比从没写过开始写要快得多,本文就介绍一个比较有意思但是也很简单的案例–搜索关键字高亮

思路分析

  1. 当我们需要对关键词高亮的时候,先决条件是什么呢?毫无疑问,是我们需要对数据进行匹配,找到和关键词相匹配的内容
  2. 而找到这个内容之后,如何进行高亮呢?在页面中,我们需要对文字进行颜色改变或者其他样式设置的时候,是不是都需要给其包裹一个标签,这里也不例外,假设我们有一段数据是:123456,我们搜索的是 23,我们需要对这段文本改造为 1<span>23</span>456,而后我们对这个 span 标签设置不同的颜色或者其他样式,在显示到页面上,是不是就可以了呢

具体实现

  1. 我们先看一下样式布局吧,这个样式布局非常简单,我就只展示显示的效果了,可以自己实现,或者在文章末尾直接复制源码,如图:

    在这里插入图片描述

  2. 现在就是根据我们的分析来具体实现,准备的数据如下:

    const data = [
    	'我们等待着戈多,在等待的过程中发现戈多就是等待本身。--王希明',
    	'我们登上并非我们所选择的舞台,演出并非我们所选择的剧本。--Enchiridion',
    	'慢慢来,谁还没有一个努力的过程。--网易云音乐',
    	'上了陆地的鱼就不能再叫做鱼了。--三体:黑暗森林',
    	'历史的发展是不以人的意志为转移的。--毛泽东',
    	'人生天地间,忽如远行客。--古诗十九首',
    	'甲之蜜糖,乙之砒霜。--曼陀罗',
    	'回眸一笑百媚生,六宫粉黛无颜色。--长恨歌',
    	'天之涯,地之角,知交半零落,一壶浊酒尽余欢,今宵别梦寒。--送别',
    	'荒诞也好,愚笨也好,总会过去的。--一瞬的光和永远'
    ]
    
  3. 获取 dom,绑定事件如下:

    const contentList = document.querySelector('.content-list')
    const inp = document.querySelector('.inp')
    
    form.addEventListener('submit', function (e) {
    	e.preventDefault()
    	render(data, inp.value)
    })
    
  4. 是不是发现了藏在这个事件里面的 render 函数呢?我们的核心就是实现这个函数,这个函数接收两个参数,一个是数据列表,一个是关键词,于是我们可以根据写出 render 函数的函数签名,如下:

    function render(list, keyword){
        
    }
    
  5. 然后我们就应该来思考一下,前置条件,在这里,我们明显只有一个条件,那就是有没有关键词,有的话如何,没有的话又如何,首先我们第一步是不是要通过这个有没有关键词进行筛选数据呢?

    function render(list, keyword){
    	let newList = list
    	if (keyword) {
    		// 根据关键词输入的筛选数据
    		newList = list.filter(item => item.includes(keyword))
    	}
    }
    
  6. 在筛选数据的时候,就可以感觉到如果需要往下执行,我们还缺少一个条件,关键词匹配的条件,关键词匹配,我们可以想到什么?是不是正则表达式呢?所以我们还需要定义条件,当有关键词的时候,需要创建一个正则表达式,如下:

    function render(list, keyword) {
    	let newList = list
    	let reg
    	if (keyword) {
    		newList = list.filter(item => item.includes(keyword))
            // 创建正则表达式
    		reg = new RegExp(keyword, 'gi')
    	}
    
    }
    
  7. 而有了这个筛选后的数据和正则,我们就可以进行真正的渲染了,这个渲染可以手动通过方法创建元素,也可以直接设置 html 字符串,我这里方便演示,就直接使用设置 html 字符串了,如下:

    function render(list, keyword) {
    	let newList = list
    	let reg
    	if (keyword) {
    		newList = list.filter(item => item.includes(keyword))
            // 创建正则表达式
    		reg = new RegExp(keyword, 'gi')
    	}
    	contentList.innerHTML = newList.map(item=>{
            // 设置默认值
            let content = item
            // 如果存在有正则表达式存在则表示需要对内容进行关键词匹配
            if (reg) {
                // 将匹配的关键词通过 replace 方法进行替换-并重新赋值给 content
    			content = item.replace(reg, `<span class="highlight">${keyword}</span>`)
    		}
            // 返回组装的 html 字符串
            return `<div class="item-box">
           				 <p class="item-content">${content}</p>
          			</div>`
        }).join('')
    }
    
  8. 这里我们给高亮的 span 的类名定义为 highlight,所以响应的我们需要再 css 文件中定义这样的一个高亮关键词样式,如下:

    /* 设置关键词样式 */
    .item-content .highlight {
    	color: #ff4757;
    	font-weight: bold;
    }
    
  9. 我们最后来看一下展示的效果,如图:

    在这里插入图片描述

  10. 这个数据的筛选,是不是需要,可以自己根据自己的需求来设计,这个案例整体是不是还是比较简单呢

源码

  • 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 = list
    	let reg
    	if (keyword) {
    		newList = list.filter(item => item.includes(keyword))
    		reg = new RegExp(keyword, 'gi')
    	}
    
    	contentList.innerHTML = newList
    		.map(item => {
    			let content = item
    			if (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, '')
    
  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值