JS获取输入内容匹配页面关键字,并修改样式

本文介绍如何使用JavaScript监听输入框内容变化,实时查找页面中与输入内容匹配的关键字,并对匹配的关键字进行高亮显示,提升用户体验。


<head>
    <meta charset="UTF-8">
    <title></title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <link href="../../css/mui.min.css" rel="stylesheet" />
</head>
<body>
    <div id="content">
        <span>哈</span></br>
        <span>哈哈2</span></br>
        <span>哈哈哈3</span></br>
        <span>哈哈哈哈4</span></br>
        <span>哈哈哈哈哈5</span></br>
    </div>
    <button id="confirmBtn">按钮</button>
    <script src="../../js/mui.min.js"></script>
    <script src="../../js/jquery-1.8.0.min.js"></script>
    <script type="text/javascript">
        mui.init();
        document.getElementById("confirmBtn").addEventListener('tap', function(e) {
            e.detail.gesture.preventDefault(); //修复iOS 8.x平台存在的bug,使用plus.nativeUI.prompt会造成输入法闪一下又没了
            var btnArray = ['取消', '确定'];
            mui.prompt('测试测试:', '性能好', '', btnArray, function(e) {
                if(e.index == 1) {
                    var input = e.value; //输入框的值
                    var old = $('#content').html(); //整个外层容器
                    $('#content').html(old.replace(input, "<span style='color:red;'>" + input + "</span>")); //替换并修改样式
                } else {
                    info.innerText = '你点了取消按钮';
                }
            })
        });
    </script>
</body>


这里写图片描述

<think>我们参考提供的多个引用,它们展示了在Vue中实现关键字高亮和搜索匹配的不同方法。用户的需求是实现一个根据输入关键字自动出现匹配内容的搜索功能,这通常称为“自动完成”或“搜索建议”功能。 根据引用,我们可以总结出以下要点: 1. 使用v-model绑定输入框的值(如searchText)来实时获取用户输入。 2. 根据输入关键字,过滤数据列表,得到匹配项(如使用indexOf或正则表达式进行模糊匹配)。 3. 将匹配关键字在结果中高亮显示(使用replace方法结合正则表达式替换为带有样式的HTML标签,用v-html渲染)。 4. 将过滤和高亮处理后的结果列表展示出来。 我们需要实现的功能包括: - 实时监听输入框的变化(使用@input或watch) - 模糊匹配数据列表 - 高亮显示匹配关键字 - 展示匹配结果列表 下面我们将逐步构建这个功能: 步骤1:设置基本结构 - 在Vue组件中,定义输入框(使用v-model绑定一个变量,例如searchText)和用于显示匹配结果的区域。 - 定义数据列表(全部数据)和匹配后的列表(filteredList)。 步骤2:监听输入框的变化 - 可以使用watch来监听searchText的变化,或者使用@input事件处理函数。 步骤3:实现模糊匹配 - 当searchText不为空时,遍历数据列表,检查每个项目是否包含关键字(不区分大小写)。 - 可以使用indexOf、includes或者正则表达式。 步骤4:实现关键字高亮 - 创建一个方法,将匹配到的关键字替换为带有样式的HTML字符串(注意:使用v-html渲染,但要注意XSS攻击风险,如果数据可信可以使用)。 - 如:brightenKeyword(text, keyword) 方法。 步骤5:展示结果 - 使用v-for遍历filteredList,在展示文本的地方使用v-html绑定经过高亮处理后的字符串。 步骤6:考虑性能优化 - 如果数据量大,可以使用防抖(debounce)来减少实时搜索的频率。 下面是一个代码示例: 模板部分: ```html <template> <div> <input type="text" v-model="searchText" placeholder="请输入关键字" @input="handleInput"> <ul> <li v-for="(item, index) in filteredList" :key="index" v-html="brightenKeyword(item.title, searchText)"></li> </ul> </div> </template> ``` 脚本部分: ```javascript export default { data() { return { searchText: '', fullList: [ // 全部数据 { id: 1, title: "迪迦奥特曼" }, { id: 2, title: "泰罗奥特曼" }, { id: 3, title: "哥斯拉怪兽" }, // ... 其他数据 ], filteredList: [] // 匹配后的列表 }; }, methods: { handleInput() { // 如果输入为空,则清空匹配列表 if (!this.searchText.trim()) { this.filteredList = []; return; } // 进行模糊匹配 const keyword = this.searchText.toLowerCase(); this.filteredList = this.fullList.filter(item => item.title.toLowerCase().includes(keyword) ); }, brightenKeyword(text, keyword) { if (!keyword.trim()) return text; const reg = new RegExp(keyword, 'gi'); return text.replace(reg, match => `<span style="color: red; background-color: yellow;">${match}</span>`); } } }; ``` 注意:上面的高亮函数中,我们使用了正则表达式全局匹配且不区分大小写('gi')。但是要注意,如果关键字中包含特殊字符(如.、*等),需要先进行转义,否则正则表达式会出错。因此,我们需要一个转义函数来安全地处理关键字。 改进:添加转义函数 ```javascript escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // 转义正则中的特殊字符 }, brightenKeyword(text, keyword) { if (!keyword.trim()) return text; const escapedKeyword = this.escapeRegExp(keyword); const reg = new RegExp(escapedKeyword, 'gi'); return text.replace(reg, match => `<span style="color: red; background-color: yellow;">${match}</span>`); } ``` 另外,考虑到性能,我们可以使用防抖来优化输入事件,例如使用lodash的debounce或者自己实现一个简单的防抖。 上面的示例中,我们直接使用了@input,没有防抖,在输入时会频繁触发。我们可以添加防抖: ```javascript created() { this.debouncedInput = _.debounce(this.handleInput, 300); // 使用lodash }, methods: { handleInput() { ... }, // ... 其他方法 } ``` 然后在模板中: ```html <input ... @input="debouncedInput"> ``` 如果没有lodash,可以自己实现一个简单的防抖函数。 另外,引用[3]中展示了在输入框按回车键触发搜索(@keydown.enter),我们这里只需要实时显示匹配列表,所以不需要回车。 引用[4]中展示了另一种方式,它先将过滤后的结果列表进行高亮处理再存储到一个新的数组中(machlist),然后展示。我们的示例中是在模板中实时调用brightenKeyword方法进行高亮,这样可能会影响性能(因为每次渲染都会重新计算)。如果数据量不大可以接受,或者我们可以像引用[4]那样在过滤的同时就处理好高亮,然后将处理好的对象数组赋给filteredList,这样模板中直接使用v-html="item.highlightedTitle"即可。 我们可以选择在过滤的同时生成高亮后的字符串,避免在模板中调用方法: ```javascript handleInput() { if (!this.searchText.trim()) { this.filteredList = []; return; } const keyword = this.searchText.toLowerCase(); const escapedKeyword = this.escapeRegExp(this.searchText); // 注意:这里使用原关键字(未转小写)转义,因为高亮要保持原大小写 const reg = new RegExp(escapedKeyword, 'gi'); this.filteredList = this.fullList .filter(item => item.title.toLowerCase().includes(keyword)) .map(item => { const highlightedTitle = item.title.replace(reg, match => `<span style="color: red; background-color: yellow;">${match}</span>`); return { ...item, highlightedTitle }; // 创建一个新对象,包含高亮后的标题 }); } ``` 然后在模板中: ```html <li v-for="(item, index) in filteredList" :key="index" v-html="item.highlightedTitle"></li> ``` 这样在过滤的同时处理高亮,避免了在模板中调用函数,性能更优。 最后,注意XSS攻击:如果数据来源不可信,使用v-html可能会有风险。确保数据安全。 综上所述,我们实现了Vue中根据输入关键字自动显示匹配内容的功能,包括模糊匹配关键字高亮。 §§相关问题§§ 1. 如何优化Vue中关键字搜索的性能(如防抖、虚拟滚动)? 2. 在Vue中如何安全地使用v-html来防止XSS攻击? 3. Vue中如何实现搜索结果的键盘导航(上下选择)? </think>### 在Vue中实现关键字自动匹配搜索功能的方法 在Vue中实现根据输入关键字自动显示匹配内容的搜索功能,需要结合**数据过滤**、**关键词高亮**和**实时响应**三个核心模块。以下是完整实现方案: #### 1. 基础结构实现 ```html <template> <div> <!-- 搜索输入框 --> <input type="text" v-model="searchText" placeholder="输入关键字" @input="handleSearch" > <!-- 匹配结果展示 --> <ul v-if="filteredList.length"> <li v-for="(item, index) in filteredList" :key="index"> <span v-html="highlightMatch(item.title, searchText)"></span> </li> </ul> <p v-else>无匹配结果</p> </div> </template> ``` #### 2. 核心JavaScript逻辑 ```javascript export default { data() { return { searchText: "", // 绑定输入内容 rawData: [ // 原始数据源 { id: 1, title: "迪迦奥特曼" }, { id: 2, title: "泰罗奥特曼" }, { id: 3, title: "哥斯拉怪兽" }, // ...其他数据 ], filteredList: [] // 过滤后的匹配结果 }; }, methods: { // 实时搜索处理 handleSearch() { if (!this.searchText.trim()) { this.filteredList = []; return; } const keyword = this.searchText.toLowerCase(); this.filteredList = this.rawData.filter(item => item.title.toLowerCase().includes(keyword) ); }, // 关键词高亮处理 highlightMatch(text, keyword) { if (!keyword) return text; // 转义正则特殊字符(安全处理) const escapedKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const reg = new RegExp(escapedKeyword, "gi"); return text.replace( reg, match => `<span style="color:#3C8AFF;font-weight:bold">${match}</span>` ); } } }; ``` #### 3. 关键实现细节说明 1. **实时响应机制**: - 通过`v-model`绑定输入内容到`searchText` - 使用`@input`事件实现**边输入边搜索** - 自动过滤空值:`!this.searchText.trim()`判断 2. **模糊匹配逻辑**: - 统一转为小写比较:`toLowerCase()`实现不区分大小写 - 使用`includes()`进行子串匹配 - 自动过滤无结果情况 3. **安全高亮处理**: - 正则特殊字符转义:`/[.*+?^${}()|[\]\\]/g` - 使用`RegExp`构造函数动态生成正则表达式 - 通过`v-html`渲染高亮HTML片段 4. **性能优化点**: - 添加防抖处理(示例): ```javascript import { debounce } from 'lodash'; methods: { handleSearch: debounce(function() { // 搜索逻辑 }, 300) } ``` - 大数据量时考虑虚拟滚动 #### 4. 完整功能扩展建议 1. **键盘导航支持**: ```javascript // 添加data属性 currentIndex: -1 // 在@keydown事件中处理 handleKeydown(e) { if (e.key === 'ArrowDown') { this.currentIndex = Math.min(this.currentIndex + 1, this.filteredList.length - 1); } // 其他方向键处理... } ``` 2. **异步数据加载**: ```javascript async handleSearch() { if (this.searchText.length < 2) return; const res = await axios.get('/api/search', { params: { keyword: this.searchText } }); this.filteredList = res.data; } ``` 3. **高亮样式优化**: ```css .highlight { background: linear-gradient(120deg, #f6d365 0%, #fda085 100%); padding: 0 2px; border-radius: 3px; } ``` ### 实现效果说明 1. 用户输入关键字时实时显示匹配项 2. 匹配部分自动高亮显示 3. 无输入匹配结果时自动隐藏列表 4. 支持中文/英文大小写智能匹配 > 注意:实际项目中如果渲染用户输入内容,需要使用`DOMPurify`等库对高亮HTML做XSS防护处理[^1][^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值