微信开发小程序 渲染html

2019-11-04 20:44:54 daimakk123456 阅读数 170

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

解决方案

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中的特殊字符是「<」和「>」,前者为开始符,后者为结束符。

•如果待解析内容以开始符开头,则截取 开始符到结束符之间 的内容作为节点进行解析。
•如果待解析内容不以开始符开头,则截取 开头到开始符之前 (如果开始符不存在,则为末尾)的内容作为纯文本解析。
•剩余内容进入下一轮解析,直到无剩余内容为止。

对web前端这门技术感兴趣的小伙伴可以加入到我们的学习圈来,编程工作第六个年头了,与大家分享一些学习方法,实战开发需要注意的细节。784-783-012 秋裙。从零基础开始怎么样学好前端。看看前辈们是如何在编程的世界里傲然前行!不停更新最新的教程和学习方法(web前端系统学习路线,详细的前端项目实战教学视频,PDF),有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入。我们会一起结伴同行学习前端我们是认真的

正如下图所示:

image.png

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

•如果截取出来的内容是开始标签,则根据匹配出的标签名和属性,在当前上下文节点下创建一个子节点。如果该标签不是自结束标签(br、img等),就把上下文节点设为新节点。
•如果截取出来的内容是结束标签,则根据标签名关闭当前上下文节点(把上下文节点设为其父节点)。
•如果是纯文本,则在当前上下文节点下创建一个文本节点,上下文节点不变。
过程正如下面的表格所示:

image.png

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

对比
把上述算法与其他类似的解析算法进行对比(性能以「解析10000长度的HTML代码」进行测定):

image.png

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

#模板渲染

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

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

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

以下为需要重复嵌套的模板(精简过),在其代码的开始前和结束后分别插入特殊注释进行标识,并在需要嵌入下一层模板的地方以另一段特殊注释(「」)标识:

<!-- wepyhtml-repeat start -->
<template name="wepyhtml-0">
	<block wx:if="{{ content }}" wx:for="{{ content }}">
		<block wx:if="{{ item.type === 'node' }}">
			<view class="wepyhtml-tag-{{ item.name }}">
				<!-- next template -->
			</view>
		</block>
		<block wx:else>{{ item.text }}</block>
	</block>
</template>
<!-- wepyhtml-repeat end -->

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

web前端开发学习Q-q-u-n:784783012 ,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
// wepy.config.js
{
	plugins: {
		replace: {
			filter: /\.wxml$/,
			config: {
				find: /<\!-- wepyhtml-repeat start -->([\W\w]+?)<\!-- wepyhtml-repeat end -->/,
				replace(match, tpl) {
					let result = '';
					// 反正不要钱,直接写个20层嵌套
					for (let i = 0; i <= 20; i++) {
						result += '\n' + tpl
							.replace('wepyhtml-0', 'wepyhtml-' + i)
							.replace(/<\!-- next template -->/g, () => {
								return i === 20 ?
									'' :
									`<template is="wepyhtml-${ i + 1 }" wx:if="{{ item.children }}" data="{{ content: item.children"></template>`;
							});
					}
					return result;
				}
			}
		}
	}
}

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

<block wx:if="{{ $htmlContent$wepyHtml$content }}" wx:for="{{ $htmlContent$wepyHtml$content }}">

「WePY」在生成组件代码时,为了避免组件数据与页面数据的变量名冲突,会 根据一定的规则给组件的变量名增加前缀 (如上面代码中的「htmlContenthtmlContentwepyHtml$」)。所以在生成嵌套模板时,也必须使用带前缀的变量名。

先在组件代码中增加一个变量「thisIsMe」用于识别前缀:

<!-- wepyhtml-repeat start -->
<template name="wepyhtml-0">
	{{ thisIsMe }}
	<block wx:if="{{ content }}" wx:for="{{ content }}">
		<block wx:if="{{ item.type === 'node' }}">
			<view class="wepyhtml-tag-{{ item.name }}">
				<!-- next template -->
			</view>
		</block>
		<block wx:else>{{ item.text }}</block>
	</block>
</template>
<!-- wepyhtml-repeat end -->

然后修改构建代码:

replace(match, tpl) {
	let result = '';
	let prefix = '';

    // 匹配 thisIsMe 的前缀
	tpl = tpl.replace(/\{\{\s*(\$.*?\$)thisIsMe\s*\}\}/, (match, p) => {
		prefix = p;
		return '';
	});

	for (let i = 0; i <= 20; i++) {
		result += '\n' + tpl
			.replace('wepyhtml-0', 'wepyhtml-' + i)
			.replace(/<\!-- next template -->/g, () => {
				return i === 20 ?
					'' :
					`<template is="wepyhtml-${ i + 1 }" wx:if="{{ item.children }}" data="{{ ${ prefix }content: item.children }}"></template>`;
			});
	}

	return result;
}

至此,渲染问题就解决了。

#图片
为了节省流量和提高加载速度,展示富文本内容时,一般都会按照所需尺寸对里面的图片进行缩小,点击小图进行预览时才展示原图。这主要涉及节点属性的修改:

•把图片原路径(src属性值)存到自定义属性(例如「data-src」)中,并将其添加到预览图数组。
•把图片的src属性值修改为缩小后的图片URL(一般云服务商都有提供此类URL规则)。
•点击图片时,使用自定义属性的值进行预览。
为了实现这个需求,本组件在解析节点时提供了一个钩子( onNodeCreate ):

onNodeCreate(name, attrs) {
	if (name === 'img') {
		attrs['data-src'] = attrs.src;
		// 预览图数组
		this.previewImgs.push(attrs.src);
		// 缩图
		attrs.src = resizeImg(attrs.src, 640);
	}
}

对应的模板和事件处理逻辑如下:

<template name="wepyhtml-img">
	<image class="wepyhtml-tag-img" mode="widthFix" src="{{ elem.attrs.src }}" data-src="{{ elem.attrs['data-src'] || elem.attrs.src }}" @tap="imgTap"></image>
</template>
// 点击小图看大图
imgTap(e) {
	wepy.previewImage({
		current: e.currentTarget.dataset.src,
		urls: this.previewImgs
	});
}

#视频

在小程序中,video组件的层级是较高的(且无法降低)。如果页面设计上存在着可能挡住视频的元素,处理起来就需要一些技巧了:

•隐藏video组件,用image组件(视频封面)占位;
•点击图片时,让视频全屏播放;
•如果退出了全屏,则暂停播放。
相关代码如下:

<template name="wepyhtml-video">
	<view class="wepyhtml-tag-video" @tap="videoTap" data-nodeid="{{ elem.nodeId }}">
		<!-- 视频封面 -->
		<image class="wepyhtml-tag-img wepyhtml-tag-video__poster" mode="widthFix" src="{{ elem.attrs.poster }}"></image>
		<!-- 播放图标 -->
		<image class="wepyhtml-tag-img wepyhtml-tag-video__play" src="./imgs/icon-play.png"></image>
		<!-- 视频组件 -->
		<video style="display: none;" src="{{ elem.attrs.src }}" id="wepyhtml-video-{{ elem.nodeId }}" @fullscreenchange="videoFullscreenChange" @play="videoPlay"></video>
	</view>
</template>

{web前端开发学习Q-q-u-n:784783012 ,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
	// 点击封面图,播放视频
	videoTap(e) {
		const nodeId = e.currentTarget.dataset.nodeid;
		const context = wepy.createVideoContext('wepyhtml-video-' + nodeId);
		context.play();
		// 在安卓微信下,如果视频不可见,则调用play()也无法播放
		// 需要再调用全屏方法
		if (wepy.getSystemInfoSync().platform === 'android') {
			context.requestFullScreen();
		}
	},
	// 视频层级较高,为防止遮挡其他特殊定位元素,造成界面异常,
	// 强制全屏播放
	videoPlay(e) {
		wepy.createVideoContext(e.currentTarget.id).requestFullScreen();
	},
	// 退出全屏则暂停
	videoFullscreenChange(e) {
		if (!e.detail.fullScreen) {
			wepy.createVideoContext(e.currentTarget.id).pause();
		}
	}
}

本文分享就到这里了。

2018-01-25 16:56:51 qq_29651203 阅读数 16277

最新小程序商城类开发教程:

1微信小程序之侧栏分类 —— 微信小程序实战商城系列(1)

2微信小程序之仿淘宝分类入口 —— 微信小程序实战商城系列(2)

3微信小程序之购物数量加减 —— 微信小程序实战商城系列(3)

4微信小程序之商品属性分类 —— 微信小程序实战商城系列(4)

5微信小程序之购物车 —— 微信小程序实战商城系列(5)


这两天微信总是放大招,小编先把这两天最新的教程放在最上面,方便大家预览:

【官方教程】扫普通链接二维码打开小程序

微信公众号菜单配置小程序:图文教程

小程序新增六大能力!面向个人开发者开放(附个人注册流程)【小编已经注册好了,就差一个程序员】

2017.03.28夜文档/工具更新:开放了蓝牙、卡券,获取用户通讯地址和访问场景,兼容ES6 API【附官方文档】

微信小程序之wx.chooseAddress


视频教程

0【最新视频教程】8天微信小程序从入门到项目实战

1最新极客学院微信小程序视频教程(全)视频教程

2【进阶】高级API深度教程视频:微信支付,模板消息,客服会话,获取openid视频教程

3千锋教育微信小程序全套开发视频教程(视频及源码)

4微信小程序视频教程合集1 附源代码 PPT下载32个视频教程

5微信小程序视频教程合集2 附源代码 PPT下载25个视频教程


1微信小程序认证指引官方文档

2微信小程序接入指南官方文档

3微信小程序开发指南官方文档

4微信小程序平台运营规范官方文档


1官方开发者工具导入demo教程:不懂如何导入demo的往这里看

2微信小程序的服务范围查询民间出品


【新手入门】线上小程序开发这开发过程总结:

1微信小程序入门(一)文章列表

2微信小程序入门(二)UI框架

3微信小程序入门(三)request请求

4微信小程序入门(四)详情页面

5微信小程序入门(五)上滑加载下拉刷新

6微信小程序入门(六)本地缓存和搜索

7微信小程序入门(七)登录注册

8微信小程序入门(八)头像上传


墙裂推荐新手看着三篇

1【超详细】从0到1:初学者入门Demo欢迎页(全文 7322 字)【新手教程】

2【超详细】从1到2:初学者入门Demo内容列表页【新手教程】

3从2到3:初学者入门Demo内容详情页【新手教程】


这四篇是HustWolf同学自己利用寒假时间开发小程序记录的一些经验,很适合新手阅读。

1【一】微信小程序(全部代码)开发---跑步App+音乐播放器新手开发分享 必读

2【二:BUG修改】微信小程序(全部代码)开发---跑步App+音乐播放器新手开发分享 必读

3【三:图片选取以及拍照功能】微信小程序开发---跑步App+音乐播放器新手开发分享 必读

4【四:录音功能】微信小程序(全部代码)开发跑步App+音乐播放器新手开发分享 必读


这块的内容是开发者对文档的解读,适合新手阅读

18小程序极速实战开发《一》view视图容器民间出品

19小程序极速实战开发《二》scroll-view可滚动视图区域民间出品

20小程序极速实战开发《三》swiper滑块视图容器民间出品

21小程序极速实战开发《四》icon图标民间出品

22小程序极速实战开发《五》text文本民间出品

23小程序极速实战开发《六》progress进度条民间出品

24小程序极速实战开发《七》button按钮民间出品

25小程序极速实战开发《八》checkbox多选项民间出品

26小程序极速实战开发《九》form表单民间出品

27小程序极速实战开发《十》input输入框民间出品

28小程序极速实战开发《十一》label标签民间出品

29小程序极速实战开发《十二》picker滚动选择器民间出品

30小程序极速实战开发《十三》radio单选项目民间出品

31小程序极速实战开发《十四》slider滑动选择器民间出品

32小程序极速实战开发《十五》switch 开关选择器民间出品

33小程序极速实战开发《十六》textarea多行输入框民间出品

34小程序极速实战开发《十七》action-sheet显示操作菜单民间出品

35小程序极速实战开发《十八》modal显示模态弹窗民间出品

36小程序极速实战开发《十九》toast显示消息提示民间出品

37小程序极速实战开发《二十》navigator页面链接民间出品

38小程序极速实战开发《二十一》audio音频民间出品

39小程序极速实战开发《二十二》image图民间出品

40小程序极速实战开发《二十三》video视频民间出品

41小程序极速实战开发《二十四》map地图民间出品

42小程序极速实战开发《二十五》map地图API民间出品

43小程序极速实战开发《二十六》canvas画布民间出品

44小程序极速实战开发《二十七》canvas画布API民间出品

45小程序极速实战开发《二十八》wx.storage数据缓存民间出品

46小程序极速实战开发《二十九》wx.request网络请求民间出品


这个是比较早的一个入门系列,同样新手入门很适合。

47【helloworld】-微信小程序教程-入门篇【1】民间出品

48【helloworld】-微信小程序教程-入门篇【2】民间出品

49【helloworld】-微信小程序教程-入门篇【3】民间出品

50【helloworld】-微信小程序教程-入门篇【4】民间出品

51【helloworld】-微信小程序教程-入门篇【5】民间出品

52【helloworld】-微信小程序教程-入门篇【6】民间出品

53【2048】-微信小程序教程-入门篇-实战【1】民间出品

54【2048】-微信小程序教程-入门篇-实战【2】民间出品

55微信小程序开发教程-从零开始(1)民间出品

56微信小程序开发教程-从零开始(2)民间出品

57微信小程序开发教程- 从零开始(3)民间出品


布局系列:

1微信小程序开发详解---小程序布局基础民间出品

2微信小程序开发:Flex布局民间出品

3从微信小程序看待FlexBox布局

4利用screenWidth与screenHeight手算布局


填坑汇总

180%小程序开发者开发过程中会遇到的问题汇总(持续更新中民间出品

2微信小程序开发者新手跳坑指南民间出品

3微信小程序跳坑指南:新坑30枚民间出品

4微信小程序常见问题腾讯官方回答集合官方问答

5说说小程序遇到的问题民间出品


HTTPS/SSL证书相关

1从http升级到https 十分钟搞定免费 SSL 证书申请、签发和配置民间出品

2Nodejs+Express创建HTTPS服务器+WS模块创建加密的WS服务民间出品

3微信小程序配置服务端https协议《一》-申请证书民间出品

4微信小程序配置服务端https协议《二》nginx+tomcat服务器配置民间出品

5tomcat http 转 https

6微信小程序 - http请求封装

7HTTPS 协议深度解析,为什么微信小程序开发者需要关注

8【https】node插件http-proxy反向代理实现对端口的分发


这一部分是小程序具体功能实现方法教程,很实用,有时间的情况下可以先浏览一遍标题,需要的时候“Ctrl+F”即可。

1小程序框架总结

2微信小程序自定义组件:带未读数目的tab按钮

3微信小程序实例:实现tabs选项卡效果民间出品

4微信小程序-下拉刷新,上拉加载更多民间出品

5微信小程序下拉筛选菜单WXDropDownMenu组件民间出品

6微信小程序 轮播图 swiper图片组件民间出品

7WxMasonry-微信小程序实现瀑布流布局民间出品

8微信小程序编辑名片页面开发民间出品

9微信小程序中使用Promise进行异步流程处理民间出品

10合理使用微信小程序1024kb(1M)限制民间出品

11text组件,progress进度条民间出品

12微信小程序wx:for和wx:for-item的正确用法民间出品

13微信小程序基础之视图控件View、ScrollView、Swiper民间出品

14微信小程序require 引用 BASE64.JS 失败问题的分析解决民间出品

15微信小程序列表渲染多层嵌套循环及wx:key的使用民间出品

16微信小程序开发技巧及开发工具使用技巧民间出品

17微信小程序开发教程官方发布

18小程序开发之登录 附代码 

19微信小程序登录逻辑梳理民间出品

20微信小程序登录与支付简要流程民间出品

21微信小程序入门教程及实例民间出品

22微信登录流程民间出品

23微信小程序怎么开发 微信小程序开发教程分享民间出品

24宽高设置百分比无效果民间出品

25微信录制的音频格式问题民间出品

26微信小程序中JavaScript代码书写习惯与命名规范建议民间出品

27接口调用方式民间出品

28App()和Page()民间出品

29小程序开发填坑《一》图片显示不全的问题民间出品

30小程序开发填坑《四》view标签设置背景图片手机无法预览民间出品

31小程序开发填坑《五》真机上预览,背景图无效民间出品

32wx.canvasToTempFilePath民间出品

33变量污染民间出品

34openid与unionid民间出品

35mac上failed to load resource民间出品

36把wx.getUserInfo返回的拼音省名市名转成汉字民间出品

37小程序开发填坑《六》tabbar未显示,页面之间传参,picker组件取值民间出品

38push与concat的区别民间出品

39textarea 简易解决方案民间出品

40小程序开发填坑《七》request请求后台获取不到data解决方法民间出品

41小程序开发填坑《八》如何优雅地处理用户的误操作引起的多次请求民间出品

42微信小程序 +nodejs+socket.io bug民间出品

43微信小程序思维导图民间出品

44nginx+tomcat服务器配置民间出品

45微信小程序支付(微信支付)民间出品

45微信小程序开发者新手须知民间出品

109快速掌握组件及API的方法民间出品

47获取当前的地理位置民间出品

48关于小程序的地图和百度地图的转换(网友提供高德与腾讯可以无缝转换)民间出品

49微信小程序开发—使用map地图API获取城市信息实例教程民间出品

50微信小程序传值以及获取值方法民间出品

51从微信第三方服务,感受小程序的设计规范民间出品

52点击空白处隐藏input,下拉刷新,全局变量民间出品

53微信小程序进行微信支付步骤简述民间出品

54微信小程序支付流程(注意事项),小程序支付回,调民间出品

55更多开发问题请移步:小程序开发问答版块民间出品

56小程序开发填坑《九》解决:设置合法请求域名后,开发中一直提示不在合法域名民间出品

57小程序开发填坑《十一》uploadFile脱坑IIS服务器无法上传大于50K的图片民间出品

58post请求民间出品

59幻灯片,tab导航切换民间出品

60官方文档BUG,tip及QA提示一览民间出品

61小程序开发填坑《十二》show内容展示,上传文件编码问题民间出品

62列表左右滑动,左滑删除功能实现民间出品

63小程序中canvas测试心得民间出品

64动画案例之圆点沿着圆圈运动民间出品

65创建下发模板消息实例民间出品

66小程序开发填坑《十三》微信小程序部署HTTPS报错怎么办民间出品

67小程序开发填坑《四》wx.uploadFile无法上传的第三方解决民间出品

68小程序开发填坑《三》关于wx.uploadFile上传多张图片的问题民间出品

69使元素占满整个屏幕高度,修改swiper 圆点样式民间出品

70小程序开发填坑《十四》微信小程序免费SSL证书https、TLS版本问题的解决方案民间出品

71小程序开发填坑《十五》request:fail错误以及真机预览问题民间出品

72小程序开发填坑《十六》小程序网络请求中遇到的坑及解决方法民间出品

73小程序开发填坑《十七》微信小程序富文本解析自定义组件,支持HTML及markdown解析民间出品

74微信小程序实例:跳转到顶部实例民间出品

75微信小程序发现的一些小问题以及解决方案集合民间出品

76小程序开发填坑《二》navigator组件使用flex布局不兼容问题及解决方案民间出品

77使用picker封装省市区三级联动模板民间出品

78微信小程序之本地缓存民间出品

79Promise对象的链式调用(解决异步回调嵌套)民间出品

80Javascript中的神器——Promise民间出品

81Page中data数据操作和函数调用民间出品

82小程序开发填坑《十八》安卓下不解析json民间出品

83小程序框架解析《一》逻辑层和视图层民间出品

84小程序框架解析《二》配置文件及其支持的配置属性民间出品

85小程序开发填坑《十九》wx.uploadFile在安卓机the same task is working民间出品

86小程序数据访问民间出品

87小程序开发心得:千里传音(模板消息)模板消息

88小程序开发填坑《二十》Android真机环境下的bluebird.js真机

890.11.1221版本新增功能:客服消息客服消息

900.11.1221版本新增细节:扫码接口,微信支付&分享的调试微信支付

91小程序开发填坑《二十一》网络请求报错民间出品

92微信小程序页面跳转传递值民间出品

93使用后端云服务LeanCloud民间出品

94微信小程序常见FAQ(16.12.12-16.12.18)民间出品

95小程序开发填坑《二十二》scroll-view高度问题民间出品

96小程序开发填坑《二十三》文本溢出民间出品

97小程序开发填坑《二十四》swiper无法保持宽高比民间出品

98小程序开发填坑《二十五》缺少文件,错误提示真机预览

99小程序开发填坑《二十六》小程序真机预览跟本地不同民间出品

100微信小程序form表单提交(PHP后端)form表单

101后台配置域名:常用api域名配置列表(wx.uploadFile)域名配置

102小程序开发填坑《二十七》审核提供测试账号,必须提供微信授权登录审核 测试账号

103小程序开发填坑《二十八》如何让你的微信小程序审核通过审核相关

104PHP:微信小程序服务端集成微信支付微信支付

105小程序接入微信支付,你可能会遇上这些坑微信支付

106微信小程序实战教程:微信支付跳坑流程微信支付

107小程序开发填坑《二十九》view的并排, tomcat配置成https,wx.request后台数据交互https相关

108基于微信小程序canvas的图表控件,适用于wepy框架canvas

109微信小程序-ToolTip信息提示组件https相关

110java调用微信小程序API createwxaqrcode 产生二维码java调用微信小程序API

111微信小程序之MaterialDesign--input组件MaterialDesign--input组件

112微信小程序提示框toast组件—wxui的使用提示框toast组件

113微信小程序实用组件:右侧字母检索,例子(体验杠杠的)右侧字母检索

114基于微信小程序 Canvas API 实现的柱状图和趋势图柱状图和趋势图

115小程序一次性上传多个本地图片,上拉加载照片以及图片加载延迟解决之道一次性上传多个本地图片

116滑动的顶部tab选项卡,简易table表格,swiper图片显示不完整滑动的顶部tab选项卡

117小程序 使用view实现下拉刷新,上拉加载数据//加载三点实现下拉刷新,上拉加载数据//加载三点实现

118js 自定义加减乘除方法(防止js自身计算错误)js 自定义加减乘除方法

119小程序 侧滑删除(左滑删除)侧滑删除(左滑删除)

120小程序 用css实现遮罩效果用css实现遮罩效果

121小程序 用modal实现遮罩层用modal实现遮罩层

122datatables+java实现服务器端分页,排序,查询,列的显示影藏datatables+java实现服务器端分页,排序,查询,列的显示影藏

123【填坑指南】小程序 view使用bindtap传值问题view使用bindtap传值问题

124微信小程序获取用户openId获取用户openId

125无刷新修改:刷新数据不刷新页面刷新数据不刷新页面

126微信小程序----弹幕的实现(无后台)弹幕

127获取用户的信息授权弹窗,更改内容的方法信息授权弹窗,更改

128制作回到顶部按钮回到顶部按钮

129微信小程序操作按钮悬浮固定在底部操作按钮悬浮固定

130微信小程序使用font-awesome图标库使用font-awesome图标库

131微信小程序之Canvas--玩坏FlappyBird

132适用于微信小程序的图片预加载组件

133【工具】微信小程序常用工具类封装

134【填坑系列】image组件binderror实例

135微信小程序的百度地图获取地理位置

136微信小程序通讯录功能实现思路分享

137微信小程序-开发经验总结

138openid的获取

139获取数据把数据打印出来

140微信小程序使用WebService(Asp.net)进行数据交互

141微信小程序开发之Mustache语法

142微信小程序template模板的使用

143微信小程序template模板的使用

144for循环,绑定点击事件

145微信小程实战报告:接入客服消息

146微信小程序开发知识点总结

147微信小程序数据绑定以及跳转传参,事件机制简介

148小程序之基于canvas绘制高铁线路图

149微信小程序入门:模块化,网络请求封装

150小程序生成参数二维码(PHP)

151自行部署腾讯云微信小程序后端开发套件wafer后端

152图片等比例缩放 动态的获取图片的高度和宽度 动态的设置图片的高度和宽度图片处理

153微信小程序之上拉加载(分页加载)实例

154小程序可滑动的 tab-view

155拉卡拉会员小程序开发总结:条形码二维码

156微信小程序定位到当前城市

157微信小程序自定义对话框+弹出和隐藏动画详解

158电商/票务类小程序必读,如何用小程序推送消息?

159微信小程序之 满意度(五星评分)附代码

160微信小程序页面传值

161微信小程序开发的几个小技巧position、渐变色、裁圆角等

162自用样式解决方案:使用一像素边框

163微信小程序自定义弹窗

164github精选:微信小程序滚动动画,点击事件及评分星星制作

165使用mock.js提供模拟数据

166提示输入对话框prompt分享

167微信小程序 MD5js使用方法

168小程序请求接口轮播

169微信小程序左滑删除效果

170Canvas 基础绘制

171扩展微信小程序框架功能:加解密插件

172扩展微信小程序框架功能:测试辅助插件

173微信小程序 es6 promise

174微信小程序手势探索:单触摸点与多触摸点

175微信支付后台开发步骤(附后台demo)

176微信小程序-遍历数组的单选多选

177解决微信小程序银行卡号输入转换格式

178微信小程序仿android fragment可滑动的底部导航栏

179小程序几个知识点:去掉scrollview滚动条/tabar选中后字体颜

180后台传回的json数据含有html标签,无法在wxml正确显示插件

181滚动到某个位置添加class效果

182微信小程序录音文件.silk上传服务器转mp3格式插件

183关于scroll-view和下拉刷新的那些坑填坑

184微信小程序聊天系统搭建

185小程序页面跳转和跳转时的数据传递

186关于小程序动态绑定数据,动态事件处理

187微信小程序日常知识储备及开发遇到的坑

188小程序基础篇之数据解密

189大众点评点餐小程序开发经验 - 发布与推广

190github精选:艺龙小程序框架组件

191如何使用小程序画布组件绘制自动缩放正方形

192详解BOM头以及去掉BOM头的方法

193微信小程序开发之『弹出菜单』特效

194精品!【艺龙小程序】:开发项目遇到的问题以及解决方案

195微信小程序实例:美女图集:调用远程API获取图片及保存

196michael:微信小程序之自定义模态弹窗(带动画)实例

197微信小程序开发之『弹出菜单』特效

198微信小程序:微信登陆(ThinkPHP作后台)

199微信小程序之WebSocket(附小程序和服务器源码)

200微信小程序远程控制电脑屏幕,使用WebSocket

201微信小程序倒计时组件更新,加入时间校准功能

202微信小程序button 修改样式

207多张image图片排列有空隙解决方案

208“小而美”的小程序渗透测试

209微信小程序之语音识别(附小程序+服务器源码)

210【跳坑】小程序带参数二维码相关问题汇总贴

211小程序生成参数二维码(PHP)

212微信小程序条形码、二维码生成模块

213微信小程序之请求二维码(用户点击按钮生成带参二维码)

214小程序带参数二维码生成 c#后台代码

215微信小程序实现带参二维码

216微信小程序五星评分效果

217微信小程序处理用户拒绝授权情况及微信登录,登录保存等系列解决方案

218微信小程序下拉菜单效果

219微信小程序倒计时组件更新,加入时间校准功能

220微信小程序请求不能使用session,picker组件不能使用对象的解决办法

221微信小程序图片绝对定位,数据遍历的步骤

222微信小程序组件系列:form表单讲解

223【登陆相关】小程序如何支持cookies---解决方法篇(nodejs)

224微信小程序 setData 的坑

225Error之util.randomString is not a function

226微信小程序开发-form 表单提交和取值

227关于微信小程序Session的一点理解(创意)

228微信小程序-文字跑马灯效果

229微信小程序实现带刻度尺滑块

230【支付】微信小程序接入微信支付实操记录

231【支付】微信小程序微信支付接入开发


转载于:http://blog.csdn.net/zhonggaorong/article/details/72730415

2018-09-20 12:00:45 rolan1993 阅读数 3498

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

解决方案

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等),就把上下文节点设为新节点。
  • 如果截取出来的内容是结束标签,则根据标签名关闭当前上下文节点(把上下文节点设为其父节点)。
  • 如果是纯文本,则在当前上下文节点下创建一个文本节点,上下文节点不变。

过程正如下面的表格所示:

 

 

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

对比

把上述算法与其他类似的解析算法进行对比(性能以「解析10000长度的HTML代码」进行测定):

 

 

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

模板渲染

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

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

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

以下为需要重复嵌套的模板(精简过),在其代码的开始前和结束后分别插入特殊注释进行标识,并在需要嵌入下一层模板的地方以另一段特殊注释(「」)标识:

<pre class="prettyprint hljs dust" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><!-- wepyhtml-repeat start -->
<template name="wepyhtml-0">
    <block wx:if="{{ content }}" wx:for="{{ content }}">
        <block wx:if="{{ item.type === 'node' }}">
            <view class="wepyhtml-tag-{{ item.name }}">
                <!-- next template -->
            </view>
        </block>
        <block wx:else>{{ item.text }}</block>
    </block>
</template>
<!-- wepyhtml-repeat end --></pre>

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

<pre class="prettyprint hljs coffeescript" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">// wepy.config.js
{
    plugins: {
        replace: {
            filter: /\.wxml$/,
            config: {
                find: /<\!-- wepyhtml-repeat start -->([\W\w]+?)<\!-- wepyhtml-repeat end -->/,
                replace(match, tpl) {
                    let result = '';
                    // 反正不要钱,直接写个20层嵌套
                    for (let i = 0; i <= 20; i++) {
                        result += '\n' + tpl
                            .replace('wepyhtml-0', 'wepyhtml-' + i)
                            .replace(/<\!-- next template -->/g, () => {
                                return i === 20 ?
                                    '' :
                                    `<template is="wepyhtml-${ i + 1 }" wx:if="{{ item.children }}" data="{{ content: item.children"></template>`;
                            });
                    }
                    return result;
                }
            }
        }
    }
}</pre>

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

<pre class="prettyprint hljs bash" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><block wx:if="{{ $htmlContent$wepyHtml$content }}" wx:for="{{ $htmlContent$wepyHtml$content }}"></pre>

「WePY」在生成组件代码时,为了避免组件数据与页面数据的变量名冲突,会 根据一定的规则给组件的变量名增加前缀 (如上面代码中的「htmlContentwepyHtml$」)。所以在生成嵌套模板时,也必须使用带前缀的变量名。

先在组件代码中增加一个变量「thisIsMe」用于识别前缀:

<pre class="prettyprint hljs dust" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><!-- wepyhtml-repeat start -->
<template name="wepyhtml-0"> {{ thisIsMe }}
    <block wx:if="{{ content }}" wx:for="{{ content }}">
        <block wx:if="{{ item.type === 'node' }}">
            <view class="wepyhtml-tag-{{ item.name }}">
                <!-- next template -->
            </view>
        </block>
        <block wx:else>{{ item.text }}</block>
    </block>
</template>
<!-- wepyhtml-repeat end --></pre>

然后修改构建代码:

<pre class="prettyprint hljs coffeescript" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">replace(match, tpl) {
    let result = '';
    let prefix = '';

    // 匹配 thisIsMe 的前缀
    tpl = tpl.replace(/\{\{\s*(\$.*?\$)thisIsMe\s*\}\}/, (match, p) => {
        prefix = p;
        return '';
    });

    for (let i = 0; i <= 20; i++) {
        result += '\n' + tpl
            .replace('wepyhtml-0', 'wepyhtml-' + i)
            .replace(/<\!-- next template -->/g, () => {
                return i === 20 ?
                    '' :
                    `<template is="wepyhtml-${ i + 1 }" wx:if="{{ item.children }}" data="{{ ${ prefix }content: item.children }}"></template>`;
            });
    }

    return result;
}</pre>

至此,渲染问题就解决了。

图片

为了节省流量和提高加载速度,展示富文本内容时,一般都会按照所需尺寸对里面的图片进行缩小,点击小图进行预览时才展示原图。这主要涉及节点属性的修改:

  • 把图片原路径(src属性值)存到自定义属性(例如「data-src」)中,并将其添加到预览图数组。
  • 把图片的src属性值修改为缩小后的图片URL(一般云服务商都有提供此类URL规则)。
  • 点击图片时,使用自定义属性的值进行预览。

为了实现这个需求,本组件在解析节点时提供了一个钩子( onNodeCreate ):

<pre class="prettyprint hljs kotlin" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">onNodeCreate(name, attrs) {
    if (name === 'img') {
        attrs['data-src'] = attrs.src;
        // 预览图数组
        this.previewImgs.push(attrs.src);
        // 缩图
        attrs.src = resizeImg(attrs.src, 640);
    }
}</pre>

对应的模板和事件处理逻辑如下:

<pre class="prettyprint hljs dust" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><template name="wepyhtml-img">
    <image class="wepyhtml-tag-img" mode="widthFix" src="{{ elem.attrs.src }}" data-src="{{ elem.attrs['data-src'] || elem.attrs.src }}" @tap="imgTap"></image>
</template></pre>

<pre class="prettyprint hljs less" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">// 点击小图看大图
imgTap(e) {
    wepy.previewImage({
        current: e.currentTarget.dataset.src,
        urls: this.previewImgs
    });
}</pre>

视频

在小程序中,video组件的层级是较高的(且无法降低)。如果页面设计上存在着可能挡住视频的元素,处理起来就需要一些技巧了:

  • 隐藏video组件,用image组件(视频封面)占位;
  • 点击图片时,让视频全屏播放;
  • 如果退出了全屏,则暂停播放。

相关代码如下:

<pre class="prettyprint hljs dust" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;"><template name="wepyhtml-video">
    <view class="wepyhtml-tag-video" @tap="videoTap" data-nodeid="{{ elem.nodeId }}">
        <!-- 视频封面 -->
        <image class="wepyhtml-tag-img wepyhtml-tag-video__poster" mode="widthFix" src="{{ elem.attrs.poster }}"></image>
        <!-- 播放图标 -->
        <image class="wepyhtml-tag-img wepyhtml-tag-video__play" src="./imgs/icon-play.png"></image>
        <!-- 视频组件 -->
        <video style="display: none;" src="{{ elem.attrs.src }}" id="wepyhtml-video-{{ elem.nodeId }}" @fullscreenchange="videoFullscreenChange" @play="videoPlay"></video>
    </view>
</template></pre>

<pre class="prettyprint hljs clojure" style="word-wrap: break-word; margin: 0px 0px 1.5em; padding: 0.5em; text-decoration: none; font-style: normal; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; line-height: 1.5em; word-break: break-all; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">{
    // 点击封面图,播放视频
    videoTap(e) {
        const nodeId = e.currentTarget.dataset.nodeid;
        const context = wepy.createVideoContext('wepyhtml-video-' + nodeId);
        context.play();
        // 在安卓微信下,如果视频不可见,则调用play()也无法播放
        // 需要再调用全屏方法
        if (wepy.getSystemInfoSync().platform === 'android') {
            context.requestFullScreen();
        }
    },
    // 视频层级较高,为防止遮挡其他特殊定位元素,造成界面异常,
    // 强制全屏播放
    videoPlay(e) {
        wepy.createVideoContext(e.currentTarget.id).requestFullScreen();
    },
    // 退出全屏则暂停
    videoFullscreenChange(e) {
        if (!e.detail.fullScreen) {
            wepy.createVideoContext(e.currentTarget.id).pause();
        }
    }
}</pre>

开源

最后贴一下「WePY HTML」的项目仓库: https://github.com/beiliao-web-frontend/wepy-html ,具体使用方法见项目内的 README 。如果你在使用过程中遇到了问题,或者是有好的建议和意见,都可以在 Issues 中提出。

原文:Heero's Blog

2018-09-28 15:05:07 weixin_41866622 阅读数 2093

新手入门,大神勿喷。。。。

渲染小程序的前端页面入门步骤(非云开发项目)

1.进入官网注册appId并且下载微信开发者工具

2.进入开发者工具后点击app.json文件,在pages字段下新建页面(此处新建页面会自动生成所需的四种文件,比较方便)

3.在Wechat Development Code目录下新建一个文件夹存放静态资源(图标、图片等)

4.新建的页面会有四个文件 :一、  .wxml文件:用标签语言渲染页面结构 二、 .wxss文件:设置页面组件的样式 三、  .js文件:管理页面和数据的逻辑 四、 .json文件: 设置页面的标题栏等等

5.wxml相当于web端的html,wxss相当于css,

入门过程中得一些小汇总。。。。

1.小方法的资源汇总:

  1. 页面跳转详细说明:https://blog.csdn.net/u010635353/article/details/54018118
  2. 使用wx.navigateTo传递参数的方法:https://www.jb51.net/article/124573.htm
  3. 文字排版以及布局:https://blog.csdn.net/qq_34281962/article/details/52729215
  4. 上传图片音频视频的简单方法:https://www.jb51.net/article/97957.htm
  5. display: -webkit-box; 的简单用法:https://blog.csdn.net/x1198928367/article/details/52624181
  6. 自定义弹窗的方法:https://www.cnblogs.com/liululin/p/6001437.html

2.注意事项

  1. 导航栏tabBar的list第一项必须是page配置第一项。
  2. 空格换行( \n)等转义符在view里是没有效果的,需要在text中设置decode="{{true}}"之后才可生效,而且必须在text中。
  3. picker-view里可以调用bindchange事件的e.detail.value取得一个数组,数组第一项为选项的值在data的数组里的位置。
  4. app.json里定义的导航条只在tabBar页面中会显示。
  5. 在使用wx.chooseImage这个API时,要在api外面进行var that=this 的转换,在wx.chooseImage()里面使用this,会报Cannot read property 'setData' of null 的error,而且res.tempFilePaths取得的是一个数组。
  6. 本地图片做背景时,可以用<image>标签和position:absolute;+z-index:-1;让图片置于底层,然后铺满(静态前端的蠢蛋做法哈哈)
  7. 用navigaTo跳转页面并用navigateback返回时,上一页面的状态不会自动刷新,可行的方法是在后一页面返回时执行上一页面的onload方法。。。
  8. wx.redirectTo和wx.switchTab都会先清除页面栈后跳转,所以跳转后的页面没有系统自带的返回键,而且跳转到tabBar页面只能用wx.switchTab
  9. tabBar页面的对象可以存到全局数据里,如果点击系统自带的返回按钮无法刷新页面时可以调用对应页面的对象的onLoad方法。
  10. wx.navigateTo无法打开页面 一个应用同时只能打开5个页面,当已经打开了5个页面之后,wx.navigateTo不能正常打开新页面。请避免多层级的交互方式,或者使用wx.redirectTo

 

2017-06-19 09:22:04 joelingwei 阅读数 44899

在最近微信小程序开发过程中,遇到一些文章内容是HTML富文本的,但是偏偏微信小程序本身是支持HTML标签的,所以我们在解析内容的时候就需要将内容中的HTML标签转换成微信小程序所支持的标签,其实刚开始我遇到这个问题的时候也是懵圈的,最后咨询下一位大神,告诉了我一款超好用的插件——WxParse,今天就给大伙分享分享~先附上最后我实现的效果图

实现效果

好咯,话不多说,先给大家上传送门

WxParse使用主要有以下几个步骤

1.将下载下来的插件文件夹复制到我们的项目根目录下(其中emojis文件可根据自己所需决定要或者不要,其他的文件必须要)

目录结构

2.在需要使用该插件的View(.js文件)中引入WxParse模块

Var WxParse= require('../../../wxParse/wxParse.js');

3.在需要是用的wxss中引入WxParse.wxss,也可以在app.wxss中引入

@import"../../../wxParse/wxParse.wxss";

4.进行数据绑定

以下为官方文档介绍

Var article= '<div>我是HTML代码</div>';
/**
* WxParse.wxParse(bindName , type, data,target,imagePadding)
* 1.bindName绑定的数据名(必填)
* 2.type可以为html或者md(必填)
* 3.data为传入的具体数据(必填)
* 4.target为Page对象,一般为this(必填)
** 5.imagePadding为当图片自适应是左右的单一padding(默认为0,可选)
*/
var that = this;
WxParse.wxParse('article', 'html', article,that, 5);

我的项目代码

Var article= postData.detail;
var that= this;
WxParse.wxParse('article', 'html', article,that, 5);

5.在内容页(.wxml文件)中引用该模版文件,其中data中article为bindName

导入文件
<import src="../../../wxParse/wxParse.wxml" />

引用模版
<template is="wxParse" data="{{wxParseData:article.nodes}}" />

完成后页面就能够正常渲染HTML富文本数据了,好开心,有木有!!!当然它还有更高级的表情解析,这个大家可以自行去看官方文档来进行开发~