【经验分享】如何在支付宝小程序里玩转富文本功能

简介: 【经验分享】如何在支付宝小程序里玩转富文本功能

富文本分为富文本编辑器、富文本解析器,而今天讲到的是富文本解析器。

一、我们小程序里富文本的使用情况

青团社兼职小程序里的职位详情页,在16年到现在,一直有个精品兼职的功能,显示内容为:运营配置的头图+运营包装的富文本内容。查看链接:https://m.qtshe.com/app/partdetails?partJobId=1255343 , 目前仅在一些品宣类型的活动职位详情里出现。


二、小程序里是如何解析富文本的

对于小程序内解析富文本的需求,小程序官方有提供对应的组件《rich-text》,传入nodes数组节点文件,rich-text组件就能做到解析并渲染出来html页面,而这个组件有几个小的缺陷:
  1. 只能做到解析展示,不支持video、audio等多媒体组件功能。
  2. 对于a标签无法做到点击跳转。
  3. 图片无法预览
nodes数组包含以下三个属性:

属性

说明

类型

必填

备注

name

标签名

string

支持部分受信任的 HTML 节点

attrs

属性

object

支持部分受信任的属性,遵循 Pascal 命名法

children

子节点列表

array

结构和 nodes 一致

需要注意:attrs属性内只支持 class 和 style 属性,不支持 id 属性
Page({
  data: {
    nodes: [{
      name: 'div',
      attrs: {
        class: 'wrapper',
        style: 'color: #00cc88;',
        id: 'container' // 这是错误的
      },
      children: [{
        type: 'text',
        text: 'Hello World!'
      }, {
        name: 'span',
        attrs: {
          class: 'wrapper',
          style: 'color: #00cc88;',
        },
        children: [{
          type: 'text',
          text: '111'
        }],
    }],
  }
});
<div>Hello world<span>111<span></div>
由于服务端返回的是html string源文件,不是被rich-text组件识别的 nodes 数组节点文件,这就需要我们对html string做一层DOM Parser。

三、如何实现DOM Parser

针对html string格式的富文本,我们需要将它转换为nodes数组,才能被小程序的富文本组件rich-text进行识别并渲染。这里我们会使用到一个官方提供的插件:mini-html-parser2
  • 首先安装依赖
npm install mini-html-parser2 --save
  • 然后代码里引入
<rich-text nodes="{{nodes}}"></rich-text>


const html = `<div>青团社兼职</div>`
import parse from 'mini-html-parser2';
Page({
  data: {
    nodes: [],
  },
  onLoad() {
    parse(html, (err, nodes) => {
      if (!err) {
        this.setData({
          nodes,
        });
      }
    })
  },
})

为什么我们的小程序里没有使用到mini-html-parser2,主要是因为我们的支付宝小程序之前是使用的wxParser插件,目前该插件已停止维护。微信小程序使用的是Parser插件【目前已改名mp-html】,一个由个人开发者维护的项目。(已邀请作者支持了支付宝小程序版本)

四、Parser [mp-html]的实现原理及使用指南

目前支持、微信、QQ、百度、支付宝、头条,支持第三方的Taro、chameleon、remax、kbone等框架。

文档地址


mp-html插件的优点:

  • 支持video、audio、table等组件的使用
  • 支持a标签的锚点跳转、及navigateTo webview的跳转 <a herf="https://xxxx" >
  • 支持rpx单位
  • 支持占位图、图片预览、图片长按菜单显示
  • 支持svg
  • 稳定性强
具体稳定性强在哪:
  1. 标签名中可以含有 : 等特殊字符(如 o:p
  2. 标签名和属性名大小写不敏感
  3. 属性值可以不加引号、加单引号、加双引号,也可以缺省(默认 true
  4. 属性之间可以没有空格(通过引号划分)、有空格(可以多个)、有换行符

同时,对于一些错误情况,程序也能够自动处理:

  1. 标签首尾不匹配
  2. 属性值中冒号不匹配
  3. 标签未闭合

以下情况均能正确解析:

<!-- 不同的属性格式 --> 
<font face="宋体" color='green' size=7>Hello</font> 
<!-- 标签首尾不匹配或未闭合 --> 
<div> World</section> 
<!-- 大小写搭配 --> 
<dIv StYle="color:green">!</DIv>
说这么多,该直接上手了:

访问(https://github.com/jin-yufeng/mp-html/tree/master/dist/mp-alipay)将源码下载下来,拷贝到小程序的components目录,同时引入该组件,使用方法如下

<mp-html content="{{html}}" />
const html = `<div>青团社兼职</div>`
Page({
  data: {
    html
  },
  onLoad() {
  },
})
最后了解下 实现原理:

通过html2nodes将html string转换为nodes数组后,根据遍历的当前node属性为‘img、span等html标签’进行判断,将匹配到的template模板进行循环渲染。

<template name="el">
  <block a:if="{{n.name==='img'}}">
    <image a:if="{{(opts[1]&&!ctrl[i])||ctrl[i]<0}}" class="_img" style="{{n.attrs.style}}" src="{{ctrl[i]<0?opts[2]:opts[1]}}" 
      mode="widthFix" />
    <image id="{{n.attrs.id}}" class="_img {{n.attrs.class}}" style="{{ctrl[i]===-1?'display:none;':''}}width:{{ctrl[i]||1}}px;height:1px;{{n.attrs.style}}" src="{{n.attrs.src}}" mode="{{!n.h?'widthFix':(!n.w?'heightFix':'')}}" lazy-load="{{opts[0]}}" data-i="{{i}}" onLoad="imgLoad" catchTap="imgTap" onLongTap="noop" />
  </block>
  <text a:elif="{{n.name==='br'}}">\n</text>
  <view a:elif="{{n.name==='a'}}" id="{{n.attrs.id}}" class="{{n.attrs.href?'_a ':''}}{{n.attrs.class}}" hover-class="_hover" 
    style="display:inline;{{n.attrs.style}}" data-i="{{i}}" catchTap="linkTap">
    <template is="node" data="{{childs:n.children,path:i+'_',opts:opts,ctrl:ctrl}}"></template>
  </view>
  <video a:elif="{{n.name==='video'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" autoplay="{{n.attrs.autoplay}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" muted="{{n.attrs.muted}}" object-fit="{{n.attrs['object-fit']}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" />
  <audio a:elif="{{n.name==='audio'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" author="{{n.attrs.author}}" 
    controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" name="{{n.attrs.name}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" 
    data-i="{{i}}" />
  <rich-text a:else id="{{n.attrs.id}}" style="{{n.f}};display:inline" nodes="{{[n]}}" /></template>
<template name="node">
  <block a:for="{{childs}}" a:for-item="n" a:for-index="i" a:key="i">
    <template a:if="{{!n.c}}" is="el" data="{{n:n,i:path+i,opts:opts,ctrl:ctrl}}" />
    <view a:else id="{{n.attrs.id}}" class="_{{n.name}} {{n.attrs.class}}" style="{{n.attrs.style}}">
      <template is="node" data="{{childs:n.children,path:path+i+'_',opts:opts,ctrl:ctrl}}"></template>
    </view>
  </block>
</template>
<template is="node" data="{{childs:childs,path:'',opts:opts,ctrl:ctrl}}"></template>

以上就是本期分享的内容,欢迎大家留言讨论~

目录
相关文章
|
5天前
|
小程序
微信小程序如何实现进入小程序自动连WiFi功能
微信小程序如何实现进入小程序自动连WiFi功能
|
5天前
|
小程序 Devops 开发工具
支付宝小程序入门学习之一:如何创建支付宝小程序并在手机上预览
支付宝小程序入门学习之一:如何创建支付宝小程序并在手机上预览
35 0
|
5天前
|
小程序 API
点餐小程序实战教程09-订单功能开发
点餐小程序实战教程09-订单功能开发
|
5天前
|
小程序 开发工具 数据库
零基础开发小程序第三课-列表功能开发
零基础开发小程序第三课-列表功能开发
|
5天前
|
小程序 JavaScript
微信小程序图片预览功能?
微信小程序图片预览功能?
|
5天前
|
存储 小程序 开发工具
零基础开发小程序第四课-查看功能开发
零基础开发小程序第四课-查看功能开发
|
5天前
|
小程序
微信小程序用户登陆和获取用户信息功能实现
微信小程序用户登陆和获取用户信息功能实现
16 0
|
5天前
|
前端开发 小程序
【微信小程序5】利用canvas实现纯色背景抠图功能
【微信小程序5】利用canvas实现纯色背景抠图功能
35 0
|
5天前
|
小程序 JavaScript
微信小程序长按识别图片二维码功能
微信小程序长按识别图片二维码功能
46 0
|
5天前
|
JSON 资源调度 小程序
一个强大的小程序富文本组件mp-html
一个强大的小程序富文本组件mp-html
40 0

热门文章

最新文章