在 uniApp 项目中使用 echarts tooltip 无法解析 html 标签的问题及解决

前言

如题,最近笔者所在项目组正在开发一个需要有 web,h5及App版本的项目。那么在技术选型的时候我们自然是想到了目前国内比较火的 uniApp 了,根据其官网介绍是一次开发到处使用啊,而且uni本身也是基于 vue 生态开发的,对我们之前一直使用 vue 全家桶开发的前端人员来说也是比较容易过渡(仔细一想目前如果是要开发一个同时带有 web h5和 app 的项目,除了 uni 的话,可能就是React Native(主要是开发App), weex(类似RN但是用的更少),最有前景的 Flutter(最合适但是国内暂时还没那么普及)),所以就采用 uni 的相关技术栈进行开发了。

问题复现:echarts 图表的 tooltip 无法解析 html 标签

实际开发的时候发现 uni 还是有不少坑的,有坑不要紧,怕的就是那种比较严重但是踩得人比较少甚至网上很难搜到相关案例的坑了。比如最近笔者遇到的在 uni 当中使用 echarts ,tooltip 使用 formatter 函数自定义渲染 html 标签但无法解析的问题。首先 echarts(https://echarts.apache.org/examples/zh/index.html) 是由百度开发的一款非常好用的 canvas 图标库(开箱即用),现在提交给了 Apache ,成为了 Apache 的一个顶级开源项目。一般我们需要展示一些常见图表诸如饼图、柱状图、仪表盘、热力图等等都可以直接找相关案例拿来即用。最新版 echarts 已经更新到了 5.x ,当然在本文中主要讨论的是4.x的 echarts(因 5.x 后的 echarts 在 api 层面比之老版本有不少改动)。在此我们以一个旋风图(基于柱状图(type: bar))为例,如下图

这是一个显示离婚诉讼支持率的旋风图的正常显示状态

在 PC 端,鼠标悬浮在图标中即会出现tooltip提示,tooltip 是图标配置项 option 中的一个属性,若不配置则默认展示相关数据,但是由于我们需要自定义展示一些内容,比如说上图红框中的两个带颜色的小圆点,这时候就需要配置 tooltip 属性自定义显示相关内容了,如下:

tooltip: {
            show: this.$screen.isMobile ? false : true,
            trigger: 'axis',
            axisPointer: {
              // 坐标轴指示器,坐标轴触发有效
              type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
            },
            formatter: function(param) {
              let htmlTemplate = param[0].name + '<br />'
              param.forEach(function(e, index) {
                htmlTemplate +=
                  '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' +
                  color[index] +
                  '"></span>' +
                  e.seriesName +
                  ':' +
                  Math.abs(e.data) +
                  '%<br/>'
              })
              return htmlTemplate
            }
          },

在 tooltip 的 formatter函数(代码略挫)中拼接 html 标签(用ES6的反引号会更好)展示自定义 tooltip,在普通的 vue 项目中是一切正常的,但是在 uniApp 的项目里就出现了一些问题,如下图:

tooltip 上的 html 不能被解析,原样展示

笔者当时也是被这个问题卡了很久,一筹莫展,在比对了其他页面的其他图表后发现,只有 uni 项目会出现这样的问题,但是仍然不知道问题出在哪里,于是求助于同事(大佬),同事一开始也是帮忙看了很久没看出所以然来,而笔者在网上也没搜到相关问题。那么当时临时解决就是不上 html 标签渲染,毕竟文本是正常展示的,唯一遗憾的就是少了两个带颜色的圈圈。

问题解决

第二天同事在阅读了 echarts 源码后(感恩)终于发现了问题所在,原来是 uniApp 全局定义了这个变量导致的:wx

/**
 * echarts设备环境识别
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
 * @author firede[firede@firede.us]
 * @desc thanks zepto.
 */

/* global wx */

var env = {};

if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') {
    // In Weixin Application
    env = {
        browser: {},
        os: {},
        node: false,
        wxa: true, // Weixin Application
        canvasSupported: true,
        svgSupported: false,
        touchEventsSupported: true,
        domSupported: false
    };
}
else if (typeof document === 'undefined' && typeof self !== 'undefined') {
    // In worker
    env = {
        browser: {},
        os: {},
        node: false,
        worker: true,
        canvasSupported: true,
        domSupported: false
    };
}
else if (typeof navigator === 'undefined') {
    // In node
    env = {
        browser: {},
        os: {},
        node: true,
        worker: false,
        // Assume canvas is supported
        canvasSupported: true,
        svgSupported: true,
        domSupported: false
    };
}
else {
    env = detect(navigator.userAgent);
}

以上是 echarts 4.x 版本判断设备的相关源码, 其中判断是在微信中展示的条件是 if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') ,那么恰巧 uniApp 在全局定义了 wx 这个对象并且还有 getSystemInfoSync 这个函数,这边笔者推测是因为 uni 是做多平台开发这一块的,所以确实定义了 wx 这个变量,至于 getSystemInfoSync 这个函数可能纯属巧合吧。就这样所有的 uni 页面都会被 echarts 误判为 微信h5 网页而进行 h5 对应的处理策略。而正常的话代码应该是走 else 之后的逻辑的。具体解决就是要改动源码,由于 uni 中 wx 全局对象有用故改动 echarts,又因为 echarts 是基于npm 安装的插件故只能将 echarts 从 npm 中卸载并提出相应静态包 echarts.js ,去掉针对 wx 对象的判断:

/**
 * TODO 暂时为了解决在 uniApp 环境下,当前运行环境被误识别为微信环境后,toolTip formatter函数无法解析 html 标签等问题(因 uniApp 下 window.wx 变量存在且 wx.getSystemInfoSync 作为 function 存在)
 */
if (false && typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') {
    // In Weixin Application
    env = {
        browser: {},
        os: {},
        node: false,
        wxa: true, // Weixin Application
        canvasSupported: true,
        svgSupported: false,
        touchEventsSupported: true,
        domSupported: false
    };
}

在 typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function' 前加了一个 false。这样做唯一的问题就是解决方案不普适性(不依赖 npm 包),另外不在对 wx h5 页面进行相应适配优化。之后同事在 uni 论坛提出了 issue 。

总结:

uniApp 在跨平台开发方面的确有其相当的方便性,且上手也较容易,但在实际开发时也有很多隐含的坑在,踩坑过程较痛苦。当然,遇到这一类问题时,在网上搜不到相关案例自己和同事暂时都无法解决时,阅读相关插件源码往往是最佳实践。

  • 13
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值