1. 实现效果
具体需求:顶部是搜索栏,包括搜索结果个数,目前跳到第几个,包含上一个、下一个按钮。富文本区域关键词高亮黄色,当前关键词为高亮橙色。如图
2. 版本号
用到vue3 和 uniapp , mp-html 插件版本是v2.5.0,
插件地址:https://ext.dcloud.net.cn/plugin?id=805
用npm方式打包放到compenonts文件,如图,打包步骤详见官方文档。
3. 页面具体代码
<template> <view class="htmlparsePage"> <view class="fixedTop"> <topbar :config="barConfig"></topbar> <view class="search-bar-container"> <view class="weui-search-bar__form"> <view class="weui-search-bar__box"> <icon class="weui-icon-search_in-box" type="search" size="14"></icon> <input class="weui-search-bar__input" placeholder-style="color:#b9babd;" placeholder="请输入需要搜索的关键词" v-model="keyWord" confirm-type="search" @confirm="searchSelf(keyWord)" /> <view class="weui-icon-clear" v-if="keyWord?.length > 0" @click=" () => { keyWord = '' searchSelf('') } " > <icon type="clear" size="14"></icon> </view> </view> </view> <view class="a-search" style="margin-left: 10rpx; margin-right: 10rpx" v-if="searchRes?.num"> <view class="searchNum">{{ searchIndex }}/{{ searchRes?.num }}</view> </view> <view class="a-search" style="margin-right: 10rpx" v-if="searchRes?.num" @click="preSearch"> <image mode="widthFix" src="../../static/img/up.svg"></image> </view> <view class="a-search" @click="nextSearch" v-if="searchRes?.num"> <image mode="widthFix" src="../../static/img/down.svg"></image> </view> </view> </view> <view v-if="show && data.content" class="mpHtmlRef"> <mp-html ref="mp" use-anchor search container-style="padding:10px" :content="data.content" @linktap="navigate" @preview-img="false" @show-img-menu="false" :selectable="true" :tag-style="{ table: 'border-collapse: collapse;border: solid black 1px', tr: 'border: solid black 1px', td: 'border: solid black 1px', }" @load="onMpLoaded" > </mp-html> </view> <view v-else class="emptyBox"> <empty /> </view> </view> </template> <script setup> import empty from '../../components/empty/empty' import mpHtml from '../../components/mp-html/mp-html' // 引入 import { getDocDetail } from '../../api/filterList' import topbar from '../../components/topbar/topbar.vue' import { onl oad, onUnload, onShareAppMessage } from '@dcloudio/uni-app' import { ref, reactive, onMounted, nextTick } from 'vue' const mp = ref(null) //富文本对象 const id = ref('') const show = ref(true) const keyWord = ref('') const data = reactive({ content: '', }) const barConfig = reactive({ bg_color: 'transparent', color: '#000', flag: 1, name: '法规详情', }) const searchRes = ref(null) const searchIndex = ref(1) function navigate(e) { this.$nextTick(() => { uni.navigateTo({ url: '../detail/analysis?id=' + e.href, success: function (res) {}, fail: function (res) {}, complete: function (res) {}, }) }) } onUnload(() => { uni.hideLoading() }) onLoad((options) => { id.value = options.id keyWord.value = options.searchInput || '' // 关键词高亮 getData() })标签:插件,searchIndex,const,res,value,height,html,vue3uniapps,uni From: https://www.cnblogs.com/shyhuahua/p/18382111
// 获取文本数据 const getData = async () => { uni.showLoading() getDocDetail({ id: id.value }) .then((res) => { if (res.code === 200) { data.content = res.data.content uni.hideLoading() } }) .catch((e) => { uni.hideLoading() uni.showToast({ title: '文档详情获取失败', icon: 'none', }) }) } // 处理 mp-html 加载完成 const onMpLoaded = async () => { if (keyWord.value) { searchSelf(keyWord.value) } } const searchSelf = (key) => { mp.value.search(key, true).then((res) => { searchRes.value = res searchIndex.value = 1 if (res.num === 0) { uni.showToast({ title: '没有了', icon: 'none', duration: 2000, }) } else { show.value = false res.highlight(1) res.jump(1, -343) // 高亮第 1 个结果并跳转到该位置,偏移量 show.value = true } }) } // 下一个关键词 const nextSearch = () => { show.value = false if (searchIndex.value < searchRes.value?.num) { searchIndex.value++ searchRes.value.highlight(searchIndex.value) searchRes.value.jump(searchIndex.value, -343) show.value = true } else { uni.showToast({ title: '没有了', icon: 'none', duration: 2000, }) show.value = true } }
// 上一个关键词 const preSearch = () => { show.value = false if (searchIndex.value > 1 && searchIndex.value <= searchRes.value.num) { searchIndex.value-- searchRes.value.highlight(searchIndex.value) searchRes.value.jump(searchIndex.value, -343) show.value = true } else { uni.showToast({ title: '没有了', icon: 'none', duration: 2000, }) show.value = true } } </script> <style> .htmlparsePage { height: 100%; background: #e5f7fe; } .fixedTop { background: #e5f7fe; padding-bottom: 10rpx; position: fixed; top: 0; left: 0; height: 266rpx; z-index: 999; } .mpHtmlRef { height: calc(100% - 273rpx); margin-top: 273rpx; overflow-y: auto; background: #ffffff; border-radius: 48rpx 48rpx 0px 0px; } .emptyBox { margin-top: 30vh; } .emptyBox .emptyCon image { width: 280rpx; height: 280rpx; } .search-bar-container { background: #e5f7fe; padding: 15rpx 20rpx 0; height: 60rpx; display: flex; } .weui-search-bar__input { height: 60rpx; line-height: 28px; font-size: 24rpx; color: #939699; } .weui-search-bar__form { border: unset; border-radius: 30rpx; height: 60rpx; } .weui-search-bar__box { padding-left: 70rpx; height: 60rpx; } .weui-icon-search_in-box { left: 30rpx; float: left; top: 20rpx; } .a-search { height: 60rpx; display: flex; align-items: center; background-color: #fff; border-radius: 30px; padding: 0 15rpx; } .a-search image { height: 28rpx; width: 34rpx; } .searchNum { color: #858687; } </style>