热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微信小程序中嵌套html_在微信小程序中渲染HTML内容3种解决方案及分析与问题解决...

大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题。但是,在微信小程序(下文简称为「小程序」)

大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题。但是,在微信小程序(下文简称为「小程序」)中,应当如何渲染这部分内容呢?

在微信小程序中渲染HTML内容的3种解决方案

wxParse

小程序刚上线那会儿,是无法直接渲染HTML内容的,于是就诞生了一个叫做「wxParse」的库。它的原理就是把HTML代码解析成树结构的数据,再通过小程序的模板把该数据渲染出来。

rich-text

后来,小程序增加了「rich-text」组件用于展示富文本内容。然而,这个组件存在一个极大的限制:组件内屏蔽了所有节点的事件。也就是说,在该组件内,连「预览图片」这样一个简单的功能都无法实现。

web-view

再后来,小程序允许通过「web-view」组件嵌套网页,通过网页展示HTML内容是兼容性最好的解决方案了。然而,因为要多加载一个页面,性能是较差的。

当「WePY」遇上「wxParse」

基于用户体验和功能交互上的考虑,我们抛弃了「rich-text」和「web-view」这两个原生组件,选择了「wxParse」。然而,用着用着却发现,「wxParse」也不能很好地满足需要:

我们的小程序是基于「WePY」框架开发的,而「wxParse」是基于原生的小程序编写的。要想让两者兼容,必须修改「wxParse」的源代码。

「wxParse」只是简单地通过image组件对原img元素的图片进行显示和预览。而在实际使用中,可能会用到云存储的接口对图片进行缩小,达到「用小图显示,用原图预览」的目的。

「wxParse」直接使用小程序的video组件展示视频,但是video组件的层级问题经常导致UI异常(例如把某个固定定位的元素给挡了)。

此外,围观一下「wxParse」的代码仓库可以发现,它已经两年没有迭代了。所以就萌生了基于「WePY」的组件模式重新写一个富文本组件的想法,其成果就是「WePY HTML」项目。

实现过程

解析HTML

首先仍然是要把HTML字符串解析为树结构的数据,我采用的是「特殊字符分隔法」。HTML中的特殊字符是「」,前者为开始符,后者为结束符。

如果待解析内容以开始符开头,则截取开始符到结束符之间的内容作为节点进行解析。

如果待解析内容不以开始符开头,则截取开头到开始符之前(如果开始符不存在,则为末尾)的内容作为纯文本解析。

剩余内容进入下一轮解析,直到无剩余内容为止。

为了形成树结构,解析过程中要维护一个上下文节点(默认为根节点):

如果截取出来的内容是开始标签,则根据匹配出的标签名和属性,在当前上下文节点下创建一个子节点。如果该标签不是自结束标签(br、img等),就把上下文节点设为新节点。

如果截取出来的内容是结束标签,则根据标签名关闭当前上下文节点(把上下文节点设为其父节点)。

如果是纯文本,则在当前上下文节点下创建一个文本节点,上下文节点不变。

上下文(解析前)

解析内容

上下文(解析后)

根节点

div

div

p

p

Hello world

p

p

div

div

根节点

经过上述流程,HTML字符串就被解析为节点树了。

对比

本组件算法

wxParse

parse5

性能

3~6ms

20ms左右

20ms左右

容错性

一般

文件大小(未压缩)

6kb

22kb

接近400kb

可见,在不考虑容错性(产生错误的结果,而非抛出异常)的情况下,本组件的算法与其余两者相比有压倒性的优势,符合小程序「小而快」的需要。而一般情况下,富文本编辑器所生成的代码也不会出现语法错误。因此,即使容错性较差,问题也不大(但这是需要改进的)。

模板渲染

树结构的渲染,必然会涉及到子节点的递归处理。然而,小程序的模板并不支持递归,这下仿佛掉入了一个大坑。

看了一下「wxParse」模板的实现,它采用简单粗暴的方式解决这个问题:通过13个长得几乎一模一样的模板进行嵌套调用(1调用2,2调用3,……,12调用13),也就是说最多可以支持12次嵌套。一般来说,这个深度也足够了。

由于「WePY」框架本身是有构建机制的,所以不必手写十来个几乎一模一样的模板,通过一个构建的插件去生成即可。

{{ item.text }}

以下是对应的构建代码(需要安装「wepy-plugin-replace」):

// wepy.config.js

{

plugins: {

replace: {

filter: /.wxml$/,

config: {

find: /([Ww]+?)/,

replace(match, tpl) {

let result = "";

// 反正不要钱,直接写个20层嵌套

for (let i &#61; 0; i <&#61; 20; i&#43;&#43;) {

result &#43;&#61; "

" &#43; tpl

.replace("wepyhtml-0", "wepyhtml-" &#43; i)

.replace(//g, () &#61;> {

return i &#61;&#61;&#61; 20 ?

"" :

&#96;&#96;;

});

}

return result;

}

}

}

}

}

然而&#xff0c;运行起来后发现&#xff0c;第二层及更深层级的节点都没有渲染出来&#xff0c;说明嵌套失败了。再看一下dist目录下生成的wxml文件可以发现&#xff0c;变量名与组件源代码的并不相同&#xff1a;

「WePY」在生成组件代码时&#xff0c;为了避免组件数据与页面数据的变量名冲突&#xff0c;会根据一定的规则给组件的变量名增加前缀(如上面代码中的「$htmlContent$wepyHtml$」)。

所以在生成嵌套模板时&#xff0c;也必须使用带前缀的变量名。 先在组件代码中增加一个变量「thisIsMe」用于识别前缀&#xff1a;

{{ thisIsMe }}

{{ item.text }}

然后修改构建代码&#xff1a;

replace(match, tpl) {

let result &#61; "";

let prefix &#61; "";

// 匹配 thisIsMe 的前缀

tpl &#61; tpl.replace(/{{s*($.*?$)thisIsMes*}}/, (match, p) &#61;> {

prefix &#61; p;

return "";

});

for (let i &#61; 0; i <&#61; 20; i&#43;&#43;) {

result &#43;&#61; "

" &#43; tpl

.replace("wepyhtml-0", "wepyhtml-" &#43; i)

.replace(//g, () &#61;> {

return i &#61;&#61;&#61; 20 ?

"" :

&#96;&#96;;

});

}

return result;

}

至此&#xff0c;渲染问题就解决了。

微信小程序中HTML包含图片

为了节省流量和提高加载速度&#xff0c;展示富文本内容时&#xff0c;一般都会按照所需尺寸对里面的图片进行缩小&#xff0c;点击小图进行预览时才展示原图。

这主要涉及节点属性的修改&#xff1a; 把图片原路径(src属性值)存到自定义属性(例如「data-src」)中&#xff0c;并将其添加到预览图数组。

把图片的src属性值修改为缩小后的图片URL(一般云服务商都有提供此类URL规则)。

点击图片时&#xff0c;使用自定义属性的值进行预览。 为了实现这个需求&#xff0c;本组件在解析节点时提供了一个钩子(onNodeCreate)&#xff1a;

onNodeCreate(name, attrs) {

if (name &#61;&#61;&#61; "img") {

attrs["data-src"] &#61; attrs.src;

// 预览图数组

this.previewImgs.push(attrs.src);

// 缩图

attrs.src &#61; resizeImg(attrs.src, 640);

}

}

对应的模板和事件处理逻辑如下&#xff1a;

// 点击小图看大图

imgTap(e) {

wepy.previewImage({

current: e.currentTarget.dataset.src,

urls: this.previewImgs

});

}

微信小程序中HTML包含视频

在小程序中&#xff0c;video组件的层级是较高的(且无法降低)。

如果页面设计上存在着可能挡住视频的元素&#xff0c;处理起来就需要一些技巧了&#xff1a; 隐藏video组件&#xff0c;用image组件(视频封面)占位&#xff1b; 点击图片时&#xff0c;让视频全屏播放&#xff1b; 如果退出了全屏&#xff0c;则暂停播放。

相关代码如下&#xff1a;

{

// 点击封面图&#xff0c;播放视频

videoTap(e) {

const nodeId &#61; e.currentTarget.dataset.nodeid;

const context &#61; wepy.createVideoContext("wepyhtml-video-" &#43; nodeId);

context.play();

// 在安卓微信下&#xff0c;如果视频不可见&#xff0c;则调用play()也无法播放

// 需要再调用全屏方法

if (wepy.getSystemInfoSync().platform &#61;&#61;&#61; "android") {

context.requestFullScreen();

}

},

// 视频层级较高&#xff0c;为防止遮挡其他特殊定位元素&#xff0c;造成界面异常&#xff0c;

// 强制全屏播放

videoPlay(e) {

wepy.createVideoContext(e.currentTarget.id).requestFullScreen();

},

// 退出全屏则暂停

videoFullscreenChange(e) {

if (!e.detail.fullScreen) {

wepy.createVideoContext(e.currentTarget.id).pause();

}

}

}

开源

最后贴一下「WePY HTML」的项目仓库&#xff1a; https://github.com/beiliao-web-frontend/wepy-html &#xff0c;具体使用方法见项目内的 README 。

如果你在使用过程中遇到了问题&#xff0c;或者是有好的建议和意见&#xff0c;都可以在 Issues 中提出。

随着微信小程序的不断完善相信用不了多长时间就会有一种更加完美的解决方案&#xff0c;那时我们就不会再改来改去了。更多关于微信小程序开发的文章请点击下面的相关文章



推荐阅读
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 突破MIUI14限制,自定义胶囊图标、大图标样式,支持任意APP
    本文介绍了如何突破MIUI14的限制,实现自定义胶囊图标和大图标样式,并支持任意APP。需要一定的动手能力和主题设计师账号权限或者会主题pojie。详细步骤包括应用包名获取、素材制作和封包获取等。 ... [详细]
  • 本文介绍了响应式页面的概念和实现方式,包括针对不同终端制作特定页面和制作一个页面适应不同终端的显示。分析了两种实现方式的优缺点,提出了选择方案的建议。同时,对于响应式页面的需求和背景进行了讨论,解释了为什么需要响应式页面。 ... [详细]
  • 微信小程序导航跟随的实现方法
    本文介绍了在微信小程序中实现导航跟随的方法。通过设置导航的position属性和绑定滚动事件,可以实现页面向下滚动到导航位置时,导航固定在页面最上方;页面向上滚动到导航位置时,导航恢复到原始位置;点击导航可以平滑跳转到相应位置。代码示例也给出了具体实现方法。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • Windows7企业版怎样存储安全新功能详解
    本文介绍了电脑公司发布的GHOST WIN7 SP1 X64 通用特别版 V2019.12,软件大小为5.71 GB,支持简体中文,属于国产软件,免费使用。文章还提到了用户评分和软件分类为Win7系统,运行环境为Windows。同时,文章还介绍了平台检测结果,无插件,通过了360、腾讯、金山和瑞星的检测。此外,文章还提到了本地下载文件大小为5.71 GB,需要先下载高速下载器才能进行高速下载。最后,文章详细解释了Windows7企业版的存储安全新功能。 ... [详细]
  • TCL华星成功研制出全球最窄LCD下边框模组产品
    TCL华星成功研制出全球最窄LCD下边框模组产品,该模组下边框较现有规格减小20%。面板技术和工艺的不断演变使得手机屏幕的左、右、上三边边框已达到极致规格,但下边框仍然是影响屏幕屏占比的最大因素。为了突破下边框的技术难题,TCL华星成立了专项技术团队,经过2年的攻关,他们通过创新的IC设计、面板设计、制程工艺等方面的突破,将LCD模组下边框压缩至全球最小2.4mm。 ... [详细]
author-avatar
侯贵聪_680
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有