Taro-支付宝小程序使用Antv/F2

Taro - 支付宝小程序

使用Antv/F2

前言

一开始我就有一个困惑,我用taro vue3去写支付宝小程序,那我究竟是看如何在Vue中使用还是如何在小程序中使用的文档呢❓

随即我开始了踩坑之旅,通过实践发现F2的vue版本是针对web端的,因此当我在小程序跑起来的时候直接报了一个node.parentNode获取不到的错误

上面说的是4.x版本。但从一开始我并没有直接用4.x,因为4.x开始,F2都是以jsx的方式去使用组件;我在vue3使用script setup去编写代码,所以暂时无法编写jsx。还有一个很重要的是旧项目(微信小程序)那边的F2用的是3.x

这两个版本在使用方式上改变还是挺大的,3.x用起来没有那么的挑;也正如所愿,我成功的跑起了示例,不曾想用安卓机一看,人都麻了,出现了以下的情况

  • 图表有时候满屏(我设置的宽度100%),有时候又变成了4分之一小
  • 使用v-if控制,有概率渲染不了,canvas节点在,就是没有渲染,使用v-show直接就不渲染了

上诉情况没有任何的报错,无从解决;因此我只能转向4.x继续踩坑

p.s. IOS啥毛病都没有,动画还贼丝滑

支付宝小程序接入Antv/F2 4.x版本

正式开始

1. 安装 F2 依赖

bash 复制代码
 # 安装 F2 依赖
 npm i @antv/f2 --save
 ​
 # 安装f2-context
 npm i @antv/f2-context --save

2. 配置 jsx transform

如果项目已有 jsx 编译,可忽略此步骤

bash 复制代码
 npm i @babel/plugin-transform-react-jsx -D

config/index.js增加配置

js 复制代码
 mini: {
   webpackChain(chain) {
     chain
       .merge({
       module: {
         rule: {
           F2: {
             test: /.jsx$/,
             use: {
               babelLoader: {
                 loader: require.resolve('babel-loader'),
                 options: {
                   plugins: [
                     [
                       '@babel/plugin-transform-react-jsx',
                       {
                         runtime: 'automatic',
                         importSource: '@antv/f2',
                       },
                     ],
                   ],
                 },
               },
             },
           },
         },
       },
     })
   }
 }

3.下载f2-my的源码

点击上面的地址把src文件夹的内容下载到本地,假设放到了项目的 /src/components/F2Chart下面将以这个路径举例

这也是为什么我在第一步的时候没有说安装@antv/f2-my,这里有两个坑,我们需要改一下源码

位置: /src/components/F2Chart/index.js

  • 文档得知,我们等下在使用组件的时候需要传递onRender这个props,但是在实践过程中,通过这个props名称我无法把我们自己的函数传递过去,我尝试新加一个props,从而解决了问题

    js 复制代码
     Component({
       props: {
         onRender: function onRender(_props) {},
         // 上面的onrender无法执行到,因此写了一个新的自定义prop
         render: function onRender(_props) {},
         // width height 会作为元素兜底的宽高使用
         width: null,
         height: null,
         type: '2d', // canvas 2d, 基础库 2.7 以上支持
       },
     })

    首先在props选项中增加了render,接着把原来调用props.onRender的地方改为props.render;

    分别是在didUpdatecanvasRender这两个地方

  • 还有就是他的click函数,从源码可以看到是点击canvas时触发的,但是一点击控制台就收到一个报错,说事件的Eventdetailundefined,我打印了整个Event对象,确实如此,连同源码中的target.offsetLeft也是没有的,我怀疑这部分是复制了web的过来然后没改;因此我的click函数改成了如下,我暂时用不到

    js 复制代码
     click: function click(e) {
       // 支付宝的点击event对象没有detail,这里只能改造一下不执行了
       var canvasEl = this.canvasEl;
       if (!canvasEl) {
         return;
       }
       var event = wrapEvent(e);
       canvasEl.dispatchEvent('click', event);
     }

    补充一下:在真机上有源码需要的e.detail.x,但是e.target.offsetLeft还是没有

4.编写我们的业务代码

下面举例写一个官方的上手例子

和官方一样,先写一个Chart.jsx

jsx 复制代码
 import { Chart, Interval, Axis } from '@antv/f2';
 ​
 export default (props) => {
   const { data } = props;
   return (
     <Chart data={data}>
       <Axis field="genre" />
       <Axis field="sold" />
       <Interval x="genre" y="sold" color="genre" />
     </Chart>
   );
 };
 ​

接着我们写一个taro的vue页面,F2.vue

vue 复制代码
 <template>
   <view>
     <button @click="show = !show">change</button>
     <view class="container" v-show="show">
       <gh-canvas :render="onRenderChart"></gh-canvas>
     </view>
   </view>
 </template>
 ​
 <script lang="tsx">
   import { reactive, toRefs } from 'vue';
   import Chart from './Chart';
   import { createElement } from '@antv/f2';
 ​
   definePageConfig({
     usingComponents: {
       'gh-canvas': '../../components/F2Chart',
     },
   });
 ​
   export default {
     setup() {
       const state = reactive({
         show: true,
       });
       const data = [
         { genre: 'Sports', sold: 275 },
         { genre: 'Strategy', sold: 115 },
         { genre: 'Action', sold: 120 },
         { genre: 'Shooter', sold: 350 },
         { genre: 'Other', sold: 150 },
       ];
       function onRenderChart() {
         return createElement(Chart, {
           data: data,
         });
       }
       return {
         ...toRefs(state),
         onRenderChart,
       };
     },
   };
 </script>
 ​
 <style lang="scss">
   .container {
     width: 100%;
     height: 600px;
   }
 </style>
 ​

这里有个注意点,在页面先注册一下我们下载到本地的antv/F2组件;这个时候如果你直接跑起来你会收到一个警告,虽然是个警告,但是你的代码是不行的。

[Vue warn]: Failed to resolve component: gh-canvas If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.

这个提示很明显了,我们自己取的这个组件名,gh-canvas,在构建的时候把他当做vue组件去解析了;解决办法就是配置一下vue-loader让他跳过我们的组件

但是吧,又不能在webpackchain中直接配置覆盖,于是我一顿找,终于找到了一个老哥的贡献

github.com/NervJS/taro...

接下来就简单了,让我们再次来到config/index.js增加以下配置

js 复制代码
 plugins: [
   // 你的其他插件
   // https://github.com/NervJS/taro/pull/11694
   [
     '@tarojs/plugin-framework-vue3',
     {
       vueLoaderOption: {
         compilerOptions: {
           isCustomElement: (tag) => tag.startsWith('gh-'),
         },
       },
     },
   ],
 ],

这个组件名前缀你喜欢改什么就改什么,记得在vue的template的引用同步更改就行

重新运行pnpm dev:alipay,大功告成~🎉 4.x版本在安卓上已经没有上面提到的两个问题了

总结

这里踩坑主要还是配置问题,因为我不熟悉webpackwebpackchain因此废了很大劲。还有找资料还是优先到github查找一下有没有类似的issue或者贡献,什么chatGPT没啥用,不停的说谎给出错误答案

相关推荐
Мартин.2 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。3 小时前
案例-表白墙简单实现
前端·javascript·css
数云界3 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd3 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常3 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer3 小时前
Vite:为什么选 Vite
前端
小御姐@stella3 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing3 小时前
【React】增量传输与渲染
前端·javascript·面试
eHackyd4 小时前
前端知识汇总(持续更新)
前端
万叶学编程7 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js