react native启用Hermes后,使用formatter函数echarts不显示的问题

背景

最近在使用第三方开源组件react-native-echarts-pro(对echarts做了包装,用webview渲染显示)做图表开发时发现了一个问题。

我的项目中使用了大量的formatter函数来做数据的自定义格式化工作,在项目开启Hermes引擎后,那些使用了formatter函数的图表都无法正常显示了。

问题复现

开启Hermes:

project.ext.react = [
    entryFile: "index.js",
    enableHermes: true,  // clean and rebuild if changing
]

echarts option源码:

...
{
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    axisLabel: {
      formatter: (value) => {
        return value + '(week)';
      },
    },
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line'
    }
  ]
};

echarts运行截图(非正常显示):
echarts异常显示

问题分析

通过查看Hermes官方库中的issue评论,开启Hermes后,在设备运行代码之前,为了使字节码文件较小并能快速执行,Hermes会编译所有的源码为字节码。当被编译成字节码的formatter函数跟随echarts的option注入到webview中时,是无法被webview正常解析运行的,其toString()方法的返回结果如下图。导致了echarts无法正常渲染显示。

formatter函数字节码

解决方案(不关闭Hermes)

Hermes官方给出的解决方案是在不想被编译成字节码的函数第一行添加代码'show source';,Hermes遇到到这个标识后就不会把该函数编译成字节码了。我们可以在formatter函数第一行添加代码'show source';,这样可以保证启用Hermes的同时,formatter函数也能正常被解析。

...
xAxis: {
  type: 'category',
  data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  axisLabel: {
    formatter: (value) => {
      'show source';
      return value + '(week)';
    },
  },
},
...

重新调用formatter函数的toString()结果如下:

formatter函数源码

其他问题

这里遇到的问题是react native热更新debug模式下,第一次Metro加载或是Metro reload代码后,formatter函数仍是字节码,需要触发一下热更新和echarts的重新渲染,echarts才可以正常显示,formatter函数才会不被编译为字节码。目前暂不清楚原因。

可以先Ctrl + X移除<echarts />的代码,然后hot reload,再Ctrl + V添加上<echarts />组件的代码,然后再次hot reload,这个时候echarts就正常显示出来了。

打包后执行是完全OK的,没有任何上述问题。

另一个问题是,'show source';这个特性是在Hermes 0.8.1上添加的,所以需要0.65及以上的react native版本才行。

正常显示效果:

echarts正常显示

参考连接

https://github.com/facebook/hermes/issues/114#issuecomment-887106990
https://github.com/facebook/hermes/issues/612
https://github.com/supervons/react-native-echarts-pro/issues/35

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值