小程序与富文本展示

1,769

问题

对于HTML项目而言,富文本的编辑与展示是一个常见的需求。例如我们通常希望用户可以通过富文本编辑器进行商品详情、文章详情等内容的编辑,包括插入图片、编辑文本的字体、颜色等等。

熟悉小程序开发的朋友,可能会听说过wxParse、这个库会将HTML代码转换为小程序对应的wxml代码,并结合wx:forwx:if等逻辑控制来动态展示富文本内容。

而从基础库1.4.0开始,小程序也引入了rich-text组件,可以通过将HTML字符串绑定到其nodes属性进行使用。

这听上去很好,但使用时仍存在需要解决的问题。

举一个最常见的例子来说,在富文本编辑器中插入图片后,我们通常需要类似img { width: 100%; }这样的css来辅助图片展示。然而小程序的许多组件,包括rich-editor是通过Web Components来实现的,这样的话我们无法通过在外层添加css规则来影响rich-text组件内部的样式。同时,rich-editor在渲染时,似乎是剥去了HTML字符串中的style标签部分(对于标准的Web Components,我们可以通过这种方式来给它们加上样式,不过尝试后发现小程序并不允许这么做)。那剩下的方法就是,将width: 100%;这样的css作为内联样式添加进去。 。

除了类似img、p1、blockqueto这些标签,我们项目中目前使用的富文本编辑器quill中的部分样式也是通过添加类名而非内联来实现的,因此为了能更好的展现这些内容,我们需要把样式内联进元素。

方案

为了将样式内联进去,我采取的方案是先解析HTML字符串,并在将解析后的结构重新转换为HTML字符串的过程中,将对应的样式内联进去。

首先是解析过程,包括vuewxParse内部都有对应的解析代码,我们可以传入一个对象,在解析到开标签、闭合标签、文本内容等等时,传入对象的响应处理方法都会被回调,通过实现这个对象以及响应的回调,我们可以构建HTML字符串对应的元素结构树。

接着,我们需要遍历这棵树,并将其还原为HTML字符串。在这个过程中,我们需要对节点进行处理。例如,如果我们发现当前节点是img标签,那么就为其扩展style属性。除了标签,我们可能还需要考虑当前节点的类名,并且要注意当前节点时候已经有内联的样式了。

对于标签/类名和样式的对应关系,可以简单的通过硬编码的Map来实现。如果需要更灵活一些,我们也可以从众多的css in js库中找到合适的工具来完成将CSS转换为中间数据结构的工具。

当然之前我的假设是只需要通过当前节点的标签/类名来判断需要内联的样式,不过或许会遇到更复杂的CSS规则,例如.a > .b { color: red; }。在这种情况下,从sizzle或类似的工具中,我们也可以找到可以借鉴的代码来进行选择器的判断。

以上。