forEachListenEvents 函数主要是通过 wepy 中 声明的 events 事件名和入参,借助 babel types 手动创建对应的 AST Node,最终生成对应的形如 this.eventBus.on("canceldeposit", this.canceldeposit) 形式的监听,其中,this.canceldeposit 为原有 events 中的事件被移入 methods 后的函数,相关伪代码实现如下所示:
// 根据 events 中的 methods 构建事件监听的调用// 并塞入 created 中forEachListenEvents(targetNode: types.ObjectMethod) {this.clzProperty.listenEvents.forEach((item) => {const methodsNode: any = item// 形如 this.$on('test', ()=>{})if (methodsNode?.key?.name) {// 创建 this 表达式const thisEx = t.thisExpression()// 创建 $on 表达式const ide = t.identifier('$eventBus.$on')// 合并 this.$on 表达式const om = t.memberExpression(thisEx, ide)// 创建事件名称参数节点const eventNameIde = t.stringLiteral(methodsNode.key.name.toString().trim())// 获取方法体内代码内容节点const meNode = t.memberExpression(t.thisExpression(),t.identifier(methodsNode.key.name.toString().trim()))const ceNode = t.callExpression(om, [eventNameIde, meNode])const esNode = t.expressionStatement(ceNode)// 将合成后的代码插入到 created 中targetNode.body.body.push(esNode)}}) }3.emitter vue 代码生成
构建完 Vue AST 之后 , 我们可以调用 generate 函数生成源码字符串:
transform() {const ast = this.buildCompVueAst()const compVue = this.genCode(ast)return { compVue, wxs: this.buildWxs() }}5.4 Wepy page 转换5.4.1 差异性梳理上面的章节已经给大家分析了template、component的代码转换逻辑 , 这一节主要带大家一起看下如何转换page文件 。page转换的逻辑即如何实现wepy 的 page.wpy 模块转换为 uniapp 的 page.vue 模块 。
首先我们来看下wepy 的 page 小程序实例:
<script>import wepy from 'wepy';import Counter from '../components/counter';export default class Page extends wepy.page {config = {};components = {counter1: Counter};data = https://www.huyubaike.com/biancheng/{};methods = {};events = {};onLoad() {};// Other properties}可以看到,wepy的page类也是通过继承来实现的,页面文件 page.wpy 中所声明的页面实例继承自 wepy.page 类,该类的主要属性介绍如下:
文章插图
5.4.2 核心转换设计基于page的api特性以及实现方案,具体的转换设计思路如下:
文章插图
5.4.3 痛点难点1.非阻塞异步与异步
在进行批量pages转换时,需要同时对pages.json进行读取、修改、再修改的操作,这就涉及到使用阻塞 IO/ 异步 IO来处理文件的读写,当使用异步IO时,会发起多个进程同时处理pages.json, 每个读取完成后单独处理对应的内容,数据不是串行修改 , 最终导致最终修改的内容不符合预期,因此在遇到并行处配置文件时,需要使用阻塞式io来读取文件,保障最终数据的唯一性,具体代码如下:
// merge pageConfig to app configconst rawPagesJson = fs.readFileSync(path.join(dest, 'src/pages.json'))// 数据操作fs.writeFileSync(path.join(dest, 'src', 'pages.json'),prettJson(pagesJson))2.复杂的事件机制
在转换过程中,我们也碰到一个比较大的痛点:page.wepy 继承至 wepy.page , wepy.page 代码较复杂,需要将明确部分单独抽离出来 。例如说 events 中组件间数据传递:$broadcast
、$emit
、$invoke
,$broadcast
、$invoke
需要熟悉其使用场景,转换为 Vue 中公共方法 。
5.5 Wepy WXML 转换template转换章节中提到了wepy模板中可以直接引入wxml文件,但是uni-app使用的Vue模板不支持直接引入wxml , 故我们需要将wxml文件处理为uniapp可以引入的Vue文件 。我们先来看一下wepy中引入的wxml文件的大致结构 。
<template name="foo"><view class="foo-content"><text class="text1">{{item.text1}}</text><image class="pic" src="https://www.huyubaike.com/biancheng/{{pic.url}}" mode="aspectFill"></image></view></template><template name="bar"><view class="bar-content"><image class="bar" src="https://www.huyubaike.com/biancheng/{{pic.url}}" mode="aspectFill"></image><text class="text2">{{item.text2}}</text></view></template><view class="footer">this is footer</view><!-- index.wepy --><!-- 引入文件 --><import src="https://www.huyubaike.com/biancheng/somePath/fooBar.wxml" /><!-- 确定展示的template及传入属性 --><script is="foo" data="https://www.huyubaike.com/biancheng/{{item, pic}}" /><!-- or, 此时仅会展示<template/>以外的内容即footer --><include src="https://www.huyubaike.com/biancheng/somePath/fooBar.wxml">
推荐阅读
- 之六 2流高手速成记:从SpringBoot到SpringCloudAlibaba
- Windows下自动云备份思源笔记到Gitee
- 原神和兰那库拉一起找到枝任务怎么完成
- DNF浓缩的纯洁之骸到底怎么获得(dnf浓缩的纯洁之骸在哪搬砖)
- 浓缩的异界精髓,浓缩的纯洁之骸在哪里可以得到
- dnf浓缩的纯洁之骸有什么用怎么得到(dnf怎么获得纯洁之骸)
- 地下城与勇士浓缩的纯洁之骸怎么可以弄到(地下城与勇士怎么获得极品装备)
- DNF浓缩的纯洁之骸要怎么才能得到(dnf浓缩的纯洁之骸在哪搬砖)
- 嘉峪关到张掖-嘉峪关到张掖多少公里
- DNF传说勋章怎样获得,哪里获得勋章(dnf如何快速得到勋章)