当前位置:网站首页>微信小程序搜索关键字高亮和ctrl+f搜索定位实现
微信小程序搜索关键字高亮和ctrl+f搜索定位实现
2022-06-29 08:26:00 【swag_特约男演员】
原理
高亮关键字
- 将文本存入数组,以
text标签循环渲染,当有关键字keyword时,将文本的关键字替换成%%keyword%%再分割split成数组去渲染。 - 当前节点文本等于关键字
class="{ { item == searchValue ? 'searchHigh' : ''}}"时,添加highLight样式。
———————————————————————————————————————————
到这里高亮关键字就实现了。
类似于ctrl+f搜索定位
- 小程序没有办法操作
dom元素不会返回像web端一样的dom节点。 - 给所有循环渲染的
text标签加上id。 - 利用
wx.createSelectorQuery().selectAll('.searchHigh').boundingClientRect获取所有添加了highLight样式的节点id数组 - 数组的
length就是找到关键字的总数,创建一个activeNodeIndex控制上一条和下一条。 - 当
text标签的id和数组中取出的选中id相同时,添加选中selected样式。 - 可以利用
scrollview的scrollIntoView(selector)滚动到选中的节点,前提是scrollview的enhanced属性要为true。 - 也可以用
wx.pageScrollTo。具体看你使用的场景。
效果
源码(mpx)
<template>
<view class="container">
<van-search id="searchPanel" value="{
{ searchValue }}" placeholder="请输入搜索关键词" bind:change="inpChange" />
<view class="statistic-bar">
<text>第{
{ current }}条</text>
<text>共{
{ totalKeywordNodes }}条</text>
<text style="color: #1d84f6" bindtap="handleScroll('pre')">上一条</text>
<text style="color: #1d84f6" bindtap="handleScroll('next')">下一条</text>
</view>
<scroll-view scroll-y enhanced style="height: {
{
listHeight}}px" class="listPanel">
<view class="news_item" wx:for="{
{newList}}" wx:key="index">
<view class="descBox">
<view class="news_title textoverflow">{
{ item.title }}</view>
<view class="news_text">
<text wx:for="{
{ item.jj }}" wx:for-index="secondIndex" wx:key="secondIndex" id="text_{
{index + '_'+ secondIndex}}" class="{
{ item == searchValue ? 'searchHigh' : ''}}" wx:class="{
{ {selected: 'text_'+index + '_'+ secondIndex === keywordNodes[activeNodeIndex]} }}" >{
{ item }}</text >
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script> import {
createPage } from '@mpxjs/core' createPage({
data: {
mainHeight: 0, seachPanelHeight: 0, searchValue: '', scrollView: null, // 滚动容器节点 newList: [ {
title: '关于举行机器人竞赛活动的相所发生的方式胜多负少的', jj: '内容简介中央气象台气温气温UIuouoiuo水电费水电费公司的发生的对方水电费' }, {
title: '关偶奇偶我奇偶就hi呕吼我和奇偶以后后的', jj: '内kjlkjljk防守打法你是端放开那没事的离开父母了情况没考虑为全面方水电费' }, {
title: '关于额外日围殴日头诶让你偷Irene的', jj: '内容简介中央气象台发布寒潮蓝色预警计今天20时至8日20时水电费水电费水电费公司的发生的对方水电费' }, {
title: '关于尔特瑞特认同与一体uyiuyiuyiuyiiuoui 胜多负少的', jj: '内容简介我解耦我偶奇偶我我就挨打王企鹅卖家前往颇尔恶趣味驱蚊器翁群水电费' } ], keywordNodes: [], // 存放的关键字节点ID数组 activeNodeIndex: 0 // 当前激活的节点索引 }, computed: {
listHeight () {
return this.mainHeight - this.seachPanelHeight }, totalKeywordNodes () {
return this.keywordNodes.length }, current () {
if (this.keywordNodes.length === 0) {
return 0 } else {
return this.activeNodeIndex + 1 } } }, onReady () {
this.getWindowHeight() this.getFields() this.mockData() }, methods: {
mockData () {
let temp = [] for (let i = 0; i < 4; i++) {
temp = temp.concat(this.newList) } this.setData({
newList: temp }) }, getWindowHeight () {
const that = this wx.getSystemInfo({
success (res) {
that.setData({
mainHeight: res.windowHeight }) } }) }, getFields () {
const that = this const query = wx.createSelectorQuery() query.select('#searchPanel').fields({
dataset: true, size: true }, res => {
// console.log(res) that.setData({
seachPanelHeight: res.height }) }).exec() }, // 替换关键字并分割成数组 getInf (str, key) {
return str .replace(new RegExp(`${
key}`, 'g'), `%%${
key}%%`) .split('%%') .filter(item => {
if (item) {
return true } return false }) }, // 输入改变时触发 inpChange (e) {
let key = e.detail this.setData({
activeNodeIndex: 0, keywordNodes: [], searchValue: e.detail }) // 如果关键字有值遍历新闻列表 if (key) {
this.newList.forEach(element => {
// 如果该字段已经是数组则重新变为字符串 if (element.jj instanceof Array) {
element.jj = element.jj.join('') } let newContent2 = this.getInf(element.jj, key) // 把分割的数组赋值给每一项的title element.jj = newContent2 }) // console.log(this.newList) this.$nextTick(() => {
wx.createSelectorQuery() .selectAll('.searchHigh') .boundingClientRect(res => {
let keywordNodes = res.map(item => item.id) this.setData({
keywordNodes: keywordNodes }) }) .select('.listPanel') .node(res => {
this.setData({
scrollView: res.node }) this.scrollToView(0) }) .exec() }) } }, /** * @method 将节点滚动至可视窗口 * @param {number} index */ scrollToView (index) {
// console.log("#" + this.keywordNodes[index]); this.$nextTick(() => {
this.scrollView.scrollIntoView("#" + this.keywordNodes[index]) }) }, /** * @method 控制上一条和下一条 * @param {string} type */ handleScroll (type) {
switch (type) {
case 'pre': if (this.activeNodeIndex === 0) {
this.activeNodeIndex = this.keywordNodes.length - 1 } else {
this.activeNodeIndex-- } break; default: if (this.activeNodeIndex === this.keywordNodes.length - 1) {
this.activeNodeIndex = 0 } else {
this.activeNodeIndex++ } break; } this.scrollToView(this.activeNodeIndex) } } }) </script>
<style scoped> .container {
width: 100%; overflow: scroll; --webkit-overflow-scrolling: touch-action; } .statistic-bar {
position: fixed; left: 16px; bottom: 30px; right: 16px; border-radius: 12rpx; background-color: #e6f7ff; z-index: 999; display: flex; justify-content: space-around; width: calc(100% - 16px -16px); padding: 16rpx 32rpx; box-sizing: border-box; font-size: 26rpx; box-shadow: 6rpx 6rpx 15rpx rgba(0, 0, 0, 0.125), -6rpx 0rpx 15rpx rgba(0, 0, 0, 0.125); color: #323233; } .listPanel {
box-sizing: border-box; background-color: #f5f5f5; } .news_item {
width: 100%; height: 208rpx; padding: 0 32rpx; margin: 32rpx 0; box-sizing: border-box; } .descBox {
width: 100%; height: 100%; background: #fff; border-radius: 12rpx; padding: 24rpx; box-sizing: border-box; } .news_title {
width: 100%; font-size: 32rpx; font-weight: 500; text-align: left; color: black; margin-bottom: 10rpx; } .news_text {
font-size: 26rpx; font-weight: 400; color: #909090; text-align: left; margin-bottom: 7rpx; display: -webkit-box; -webkit-line-clamp: 2; overflow: hidden; text-overflow: ellipsis; -webkit-box-orient: vertical; word-break: break-all; } .textoverflow {
display: -webkit-box; -webkit-line-clamp: 1; overflow: hidden; text-overflow: ellipsis; -webkit-box-orient: vertical; word-break: break-all; } .searchHigh {
font-size: 36rpx; color: #1d84f6; font-weight: bold; } .selected {
background: #909090; } </style>
<script type="application/json"> {
"navigationBarTitleText": "搜索关键字高亮", "usingComponents": {
"van-search": "@vant/weapp/dist/search/index" } } </script>
边栏推荐
猜你喜欢

Self attention mechanism

今年的网络安全“体检”你做了吗?

Tutorial on building open source Internet of things platform

手写 redux-thunk

La finale de la zone de compétition Hefei de la sixième saison 2022 a été couronnée de succès.

闭关修炼(二十四)浅入了解跨域问题

ThreadLocal thread variable

对比HomeKit、米家,智汀家庭云版有哪些场景化的体验

Scenario analysis of deadlock during MySQL insert

Leetcode (142) - circular linked list II
随机推荐
Let you know today that the passing rate of the PMP Exam is 97%, is it believable
Network learning of pointnet
The sixth season of 2022 perfect children's model Qingyuan competition area audition came to a successful conclusion
MySQL的分库分表策略及应用场景
verilog 等价操作符
闭关修炼(二十)如何做好单元测试
TypeScript 变量声明 —— 类型断言
Operating system product key viewing method
51 MCU interrupt and timer counter, based on Puzhong technology hc6800-esv2.0
Batch processing of experimental contact angle data matlab analysis
2022第六季完美童模 清远赛区 海选赛圆满落幕
MySQL virtual column
一般乘法器设计,verilog code
laravel 8 实现 订单表按月份水平分表
mongoDB 持久化
2022第六季完美童模 合肥賽區 决賽圓滿落幕
C# 语音端点检测(VAD)实现过程分析
MySQL row column conversion example
Verilog 数据类型
ActiveMQ message component publish subscribe redelivery message redelivery