vue3uniapps使用富文本mp-html插件
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 { onLoad, 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()
})
// 获取文本数据
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>

浙公网安备 33010602011771号