当前位置:网站首页>如何快速设计一套支持渲染富文本内容的跨端组件
如何快速设计一套支持渲染富文本内容的跨端组件
2022-07-29 01:48:00 【油墨香^_^】
背景
不知道大家有没有遇到过这种需求,在管理后台配置一段富文本 html 内容,一开始呢,只需要支持渲染到浏览器上面,但随着公司业务的变化,可能需要在小程序上使用,甚至是 ios 或者 android 等其他端上
渲染到 h5 或者类浏览器端(忽略 xss 等安全问题)
这种一般就直接使用框架自带的,类似
vue: vue-html
react: dangeroushtml
如何渲染到小程序端
因为小程序是使用自己独有的标签,例如 view 标签,但后台配置的是 html 文本字符串,怎么把 html 变成 view,往往很多人就不知道怎么做了,觉得这就是不可能完成的,是产品在提不合理的需求,看到这里,大家可以先想想,如果是你,你会怎么做?
下面说说我的思考过程
taro
因为当时我在用 taro 写小程序,简化需求来理解,就是需要把 div 标签 渲染成一个 view 标签 ,如何变呢?我一下子想到了 babel, 因为 taro 本身就支持跨端,跨端的原理就是利用 babel 做抽象语法树,变成自己想要的语言效果

看上图,一切都很明亮了,但是有两个致命的问题
babel 是静态语法分析,富文本需求是代码运行时计算的,相悖了
babel 包太大了
后来直接否决掉了 babel
这时候再抽象一下,原来需求简化过是 div 变成 view ,再简化一下就是div 变成虚拟 dom ,虚拟 dom 变成 view
html 转成虚拟 DOM
jquery
这时候想到了 jquery 的一个语法,jquery 的 $('一段html')就能把 html 变成 dom,然后一顿操作就去翻 jq 源码,并不满足, 缺点:
dom 结构挂载了太多 jq 无用的属性,
html 内容有一些 jq 框架自带的限制
vue、react
翻看 vue、react 的一些源码
vue: vue-template-compiler
react: babel-loader 会把elemennt 转化成 createElement
缺点:
解析出来的虚拟 dom 还是会带上很多框架自身的限制
难道要自己写一个?需求很紧急啊,写是不可能自己写的
babel
本质就是如何 div 变成一个干净的虚拟 dom 节点呢?最后还是绕不开回到了原点。babel,通过查看源码发现有一个名词叫 html-parse 直接打开 github 一搜,发现很多库,但是大部分都是实验或者 demo 级别
html-parse-stringify[1]
最后选择了这个库
优点:
轻量兼容性好,很多属性写法都能匹配的到生成的虚拟 dom 不依赖框架、平台,就是 json 文本
var HTML = require('html-parse-stringify')
// this html:
var html = '<div class="oh"><p>hi</p></div>'
// becomes this AST:
var ast = HTML.parse(html)
console.log(ast)
/*
{
// can be `tag`, `text` or `component`
type: 'tag',
// name of tag if relevant
name: 'div',
// parsed attribute object
attrs: {
class: 'oh'
},
// whether this is a self-closing tag
// such as <img/>
voidElement: false,
// an array of child nodes
// we see the same structure
// repeated in each of these
children: [
{
type: 'tag',
name: 'p',
attrs: {},
voidElement: false,
children: [
// this is a text node
// it also has a `type`
// but nothing other than
// a `content` containing
// its text.
{
type: 'text',
content: 'hi'
}
]
}
]
}
*/
虚拟 DOM 转化成其它端代码
有了虚拟 dom, 小程序端就可以通过深度优先遍历,一层一层的把虚拟 dom 渲染成 view 标签 实现类似于下面代码,其他端也类似同理
使用
<View className="index">
<TaroRichText
htmls={`访问内容<span class="highlight"><a appid="495ec7a9-a3e8-42ad-a1ee-f14b8e0af1e3" pagepath="pages/renderer/renderer">活动线上预约报名啦啦啦</a></span>
`}
/>
</View>
核心源码
export default function Tree(props: IProps) {
const { doms } = props;
console.log(doms);
const { children = [] } = doms || {};
return (
<View>
// 根据不同的类型,模拟不同的样式即可,通过 class 模拟
{doms.type === 'text' && <View>{doms.content}</View>}
{/* <View>{其他类型,自己写函数渲染}</View> */}
<View>
{children.length &&
children.map(dom => {
return <Tree doms={dom} />;
})}
</View>
</View>
);
}边栏推荐
- 多线程浅谈
- [simple implementation and extension of one · data | array heap]
- Interprocess communication - detailed explanation of the pipeline (explanation of graphic cases)
- 当Synchronized遇到这玩意儿,有个大坑,要注意
- QT learning notes -37.qregex and regular expressions
- 特殊流&Properties属性集实例遇到的问题及解决方法
- Work queue_ queue
- Derivation of Euler angle differential equation
- JetPack--Navigation实现页面跳转
- ResNet50+k折交叉验证+数据增强+画图(准确率、召回率、F值)
猜你喜欢

Day 14: continued day 13 label related knowledge

裂开了,一次连接池参数导致的雪崩问题

外包公司“混”了2年,我只认真做了5件事,如今顺利拿到字节 Offer。

网络安全漏洞管理的探索与实践

即时通讯场景下安全合规的实践和经验

数据安全与隐私计算峰会-安全求交集在隐私计算中的发展和应用:学习

如果时间不够,无法进行充分的测试怎么办?

Responsive dream weaving template home decoration building materials website

STM32 DMA receives serial port data

字符流综合练习解题过程
随机推荐
【上传图片2-可裁剪】
Website Collection
"Wei Lai Cup" 2022 Niuke summer multi school training camp 3, sign in question cajhf
当我看源码的时候,我在想什么?
Problems encountered in special flow & properties property set instances and Solutions
“12306”的架构到底有多牛逼?
Rgbd point cloud down sampling
3D模型格式全解|含RVT、3DS、DWG、FBX、IFC、OSGB、OBJ等70余种
[cloud native] what is the microservice architecture
【质量】代码质量评价标准
Prevent repeated clicks
Even PostgreSQL problem: expected authentication request from server, but received V
年中总结 | 与自己对话,活在当下,每走一步都算数
MySQL之数据查询(多表查询)
Hexadecimal to string
Vector similarity evaluation method
基于对象的实时空间音频渲染丨Dev for Dev 专栏
Prometheus + AlertManager 消息预警
2022.7.27-----leetcode.592
[upload pictures can be cut-1]