微信跟百度 直接使用 u-parse组件,效果还是不错的,注意一点是a标签的复制提示语,自己需要uni.hideLoading()一下,再重置。
支付宝相对复杂一点,采用原生rich-text 标签,搭配官方推荐的mini-html-parser2,处理富文本。
同时需要处理一下pc端可正常展示,但是小程序富文本不支持的部分:
let parseData = this.docBody.replace(/(\t|\n)/g,''); // 去掉所有富文本中的空格,换行等
parseData = parseData.replace(/(<script).*?(\/script>)/, '') // 替换掉会引起报错的script标签。
parseData = parseData.replace(/(<html>)|(<\/html>)/g, '') // 替换掉会引起报错的html标签。
parseData = parseData.replace(/(<body>)|(<\/body>)/g, '') // 替换掉会引起报错的html标签。
parseData = parseData.replace(/( )/g, '') // 替换掉会引起报错的html标签。
parseData = parseData.replace(/(<p><!--\[if !mso])[\s\S]*?(<!\[endif]--><\/p>)/g, '') // 替换掉会引起报错的标签。
parseData = parseData.replace(/(<style).*?(\/style>)/, '') // 替换掉会引起报错的script标签。
// <!--[if gte mso 9]> <![endif]-->
// <!--[if supportMisalignedColumns]--> <!--[endif]-->
parseData = parseData.replace(/(<!--\[if).*?(endif]-->)/g, '') // 替换掉会引起报错的标签。
直接上组件代码
<template>
<view class="wjw-rich-text">
<!-- #ifdef MP-ALIPAY -->
<rich-text :nodes="parseDocBody" @tap="handleOnTap"></rich-text>
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
<u-parse :content="parseDocBody" @linktap="linktap" :copyLink="false"></u-parse>
<!-- #endif -->
</view>
</template>
<script>
import parse from 'mini-html-parser2';
const HTML_A_TAG = 'a';
export default {
props: {
docBody: {
type: String,
default: ''
}
},
data() {
return {
parseDocBody: ''
}
},
watch: {
docBody: {
handler(val) {
let parseData = this.docBody.replace(/(\t|\n)/g,''); // 去掉所有富文本中的空格,换行等
parseData = parseData.replace(/(<script).*?(\/script>)/, '') // 替换掉会引起报错的script标签。
parseData = parseData.replace(/(<html>)|(<\/html>)/g, '') // 替换掉会引起报错的html标签。
parseData = parseData.replace(/(<body>)|(<\/body>)/g, '') // 替换掉会引起报错的html标签。
parseData = parseData.replace(/( )/g, '') // 替换掉会引起报错的html标签。
parseData = parseData.replace(/(<p><!--\[if !mso])[\s\S]*?(<!\[endif]--><\/p>)/g, '') // 替换掉会引起报错的标签。
parseData = parseData.replace(/(<style).*?(\/style>)/, '') // 替换掉会引起报错的script标签。
// <!--[if gte mso 9]> <![endif]-->
// <!--[if supportMisalignedColumns]--> <!--[endif]-->
parseData = parseData.replace(/(<!--\[if).*?(endif]-->)/g, '') // 替换掉会引起报错的标签。
// #ifndef MP-ALIPAY
this.parseDocBody = parseData
// #endif
// #ifdef MP-ALIPAY
try {
parse(parseData, (err, nodes) => {
if (err) {
console.log('parseData-err', err)
console.log('parseData', parseData)
}
if (!err) {
const recursion = (list) => {
return list.map(item => {
const { children, name, attrs } = item;
// 这里没有处理 children
if (name === HTML_A_TAG) { // 这里假定 原本的htmlstring中 a标签为原本跳转的元素
item.marks = { ...attrs, name: HTML_A_TAG }; // 小程序中不支持 a标签的href属性,先把对应的href 属性放在marks中
}
if (children) {
recursion(children)
}
return item
})
}
const transferNodes = recursion(nodes)// 递归处理a标签
this.parseDocBody = transferNodes
}
})
} catch (err) {
this.parseDocBody = ''
}
// #endif
},
immediate: true,
deep: true
}
},
methods: {
/**
*
* @param {跳转webview} e
*/
navigate(e) {
this.$util.navigateTo({
url: `/pages/publicPages/webView?url=${e}`
})
},
handleNavigate(href) {
if (href.includes('https://www.baidu.com')) {
this.$util.showToast('跳转中...', this)
this.navigate(href)
return true
}
return false
},
linktap(e) {
const { href } = e
setTimeout(()=> {
uni.setClipboardData({
data: href,
success: () => {
uni.hideLoading()
if (this.handleNavigate(href)) return
this.$util.showToast('链接已复制, 请到浏览器中查看!', this)
}
});
})
},
handleOnTap(e) {
const {
detail: { marks }, // 获取自定义的marks
} = e
const { name, href } = marks || {} //
if (name === HTML_A_TAG && href) { // 判断是否是 a 标签,同时有 href 链接
uni.setClipboardData({
data: href,
success: () => {
if (this.handleNavigate(href)) return
this.$util.showToast('链接已复制, 请到浏览器中查看!', this)
}
});
}
},
}
}
</script>