搜索文本高亮匹配

在网上冲浪的过程中,我们会发现在浏览器输入关键词进行检索后,搜索到的关键字都会高亮匹配。下面我将围绕这个场景来分享:

一.演示

二.实现思路

        这样的需求我选择了使用正则表达式,首先,用户在搜索框中输入关键词。我们需要定义变量来接收这个关键词,同时在后端完成模糊匹配查询,将查询到的数据用正则表达式匹配替换,后端响应数据中出现的关键词嵌入带特殊样式(如颜色,背景)的标签。如用户输入"通义千问",从后端查询到的数据是{"code": 200, "msg": success, "data": "通义千问是阿里训练出的一款大模型"}。那么按照前面的思路,前端渲染出来的应该是"<span style="color: #FF8C00;">通义千问</span>是阿里训练出的一款大模型",如果想对span标签设置宽高还需修改span为行内块布局。

三.编码

在Vue3 setup语法糖中:

<script setup lang="ts">

let page = ref<number>(1)
let pageSize = ref<number>(5)

let keyWord: string = ''

type paramsType = {
    currentPage: number,
    pageSize: number,
    annex: string,
    sort: string,
    message: string,
}

const state = reactive({
  data: [{
        id: 1,
        askerId: 1,
        asker: role.role === 'NPC' ? npcStore.name : people.name,
        title: '',
        detail: '',
        fileName: '',
        annex: '',
        thumbUp: 1,
        liker: <string><unknown>[],
        read: 1,
        time: '',
    }],
    params: <paramsType>{
        currentPage: page.value,
        pageSize: pageSize.value,
        annex: '综合',
        sort: 'sortFromLargeToSmall',
        message: ''
    }

})

const getData = async (): Promise<Object[]> => {
    let res = await request.get('/question/getQuestion', { params: state.params });
    if (res.data.length < 5 && res.data.length > 0) {
        disableOrNotBackward.value = true;
    } else
        disableOrNotBackward.value = false
    state.data = res.data;
    return state.data;
}

const search = async () => {
    keyWord = state.params.message;
    getData();
    state.params.message = '';
}

const regExpText = (detail: string) => {
    console.log('匹配内容: ' + keyWord);
    let reg = new RegExp(keyWord, 'gi');
    return detail.replace(reg, (match) => {
        return `<span style="color: #FF9933;"> ${match} </span>`
    })
}

</script>

<template>
<div class="contain">
        <div class="search">
            <div class="search-input">
                <el-input v-model="state.params.message" size="normal" style="margin-top: 6px;" />
            </div>
            <div class="search-btn">
                <el-button><i class="iconfont icon-sousuo" style="font-size: 27px;" @click="search()"></i></el-button>
            </div>
        </div>
        <div class="main">
            <div class="main-area">
                    <el-empty v-if="state.data.length === 0" description="暂无数据" />
                    <div v-for="(item, index) in state.data" :key="index" class="content-area">
                        <div class="word" @click="commentModel(item.id)">
                            <h3 v-html="regExpText(item.title)"></h3>
                            <div v-html="regExpText(item.detail)" class="detail"></div>
                            <div class="tag">
                                <span><i class="iconfont icon-eyes_line_b"></i>{{ item.read }}</span>
                                <span v-if="item.liker.includes(state.thumbUp.liker)" class="thumbUp"
                                    @click.stop="revoke(item.id)"><i class="iconfont icon-dianzan"></i>{{
                    item.thumbUp }}</span>
                                <span v-else class="unThumbUp" @click.stop="thumbUp(item.id, item.askerId)"><i
                                        class="iconfont icon-dianzan"></i>{{ item.thumbUp }}</span>
                                <span v-html="item.time" style="width: 99px; font-size: 13px; color: grey;"></span>
                                <div class="annex">
                                    <el-tag v-if="item.annex != ''" v-for="Item in item.annex.split(', ')"
                                        style="width: auto; margin-left: 9px; float: right;">{{ Item }}</el-tag>
                                    <span v-if="item.hot >= 60"
                                        style="color: #FF9900; width: auto; margin-left: 5px;">热门</span>
                                </div>
                            </div>
                        </div>
                        <div v-if="item.fileName != '' && item.fileName != null" class="image">
                            <img :src="getAssetURL(item.fileName)" width="66%"
                                style="margin-left: 33%; margin-top: 9%; border-radius: 5px;" />
                        </div>
                    </div>
                </div>
        </div>
</div>
</template>

 【附】后端响应数据结构

四.总结

4.1 文本高亮匹配可以用正则表达式,对关键词进行全局匹配,匹配到的文本添加特殊样式完成高亮。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值