1260215278 / miniprogram-to-uniapp

Try to transform Weixin miniprogram project to Uni-app project

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

微信小程序转换为uni-app项目

输入小程序项目路径,输出uni-app项目。

实现项目下面的js+wxml+wxss转换为vue文件,模板语法、生命周期函数等进行相应转换,其他文件原样复制,生成uni-app所需要的配置文件。

安装

$ npm install miniprogram-to-uniapp -g

升级版本

$ npm update miniprogram-to-uniapp -g

使用方法

Usage: wtu [options]

Options:

  -V, --version     output the version number [版本信息]
  -i, --input       the input path for weixin miniprogram project [输入目录]
  -o, --output      the output path for uni-app project, which default value is process.cwd() [输出目录,可不写,默认为原文件目录加上_uni后缀]
  -h, --help        output usage information [帮助信息]
  -c, --cli         the type of output project is vue-cli, which default value is false [是否转换为vue-cli项目,默认false]
  -w, --wxs         transform wxs file to js file, which default value is false [是否将wxs文件转换为js文件,默认false]

Examples:

$ wtu -i miniprogramProject

vue-cli mode [转换为vue-cli项目]:

$ wtu -i miniprogramProject -c

Transform wxs file to js file [将wxs文件转换为js文件]:

$ wtu -i miniprogramProject -w

使用指南

本插件详细使用教程,请参照:miniprogram-to-uniapp使用指南

转换注意事项

  • 小程序并不能与uni-app完全对应,转换也并非100%,只希望能尽量减少大家的工作量。
  • 此工具基于语法转换,一定会有部分代码是uni-app没法支持,或暂时没有找到替代方案,请手动调整。
  • 小程序使用wxParse组件时,转换难度挺大,建议手动替换为uni-app所对应的插件

转换规则

基本参照大佬的文章:微信小程序转换uni-app详细指南

因为小程序与uni/vue的语法以及文件结构都有很大的差别,所以做了很多的优化工作,后面再补。

已完成

  • 支持含云开发的小程序项目(有云开发与无云开发的项目的目录结构有差别)
  • 支持['btn/btn.js', 'btn/btn.wxml', 'btn/btn.wxss']或['btn/btn.js', 'btn/btn.wxml' || 'btn/btn.wxss']转换为'btn/btn.vue' ,模板语法、生命周期函数等进行相应转换
  • 支持['util/util.js']复制为['util/util.js'],原样复制
  • 解析wxss文件,修复import *.wxss语句及引用的资源路径修复
  • 支持生命周期函数的转换
  • 支持同一目录下有不同名js/wxml/wxss文件转换
  • 区分app.js/component,两者解析规则略有不同
  • 添加setData()函数于methods下,解决this.setData()【代码出处:https://ask.dcloud.net.cn/article/35020】
  • App.vue里,this.globalData.xxx替换为this.$options.globalData.xxx(后续uni-app可以支持时,此功能将回滚)
  • 支持wxs文件转换,可以通过参数配置(-w),默认为false
  • 支持vue-cli模式,即生成为vue-cli项目,转换完成需运行npm -i安装包,然后再导入hbuilder x里开发
  • 导出<template data="abc"/> 标签为abc.vue,并注册为全局组件

Todolist

  • [todo] 配置参数,支持指定目录、指定文件方式进行转换,增加参数-p 支持子目录转换
  • [todo] 文件操作的同步方法添加try catch
  • [todo] template标签转换为vue文件
  • [todo] 浏览小程序文档,发现生命周期函数可以写在lifetimes或pageLifetimes字段时,需要兼容一下(https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html)
  • [todo] 小程序组件还有其他生命周期函数转换
  • [todo] 组件批量注册
  • [todo] 删除生成目录里的空白目录
  • [todo] 转换前先格式化代码

关于不支持转换的语法说明

<import src="*.wxml"/>支持部分语法处理

常规我们见到的代码是这样的(摘自官方小程序示例demo):

<import src="../../../common/head.wxml" />
<view class="container">
    <template is="head" data="{{title: 'action-sheet'}}"/>
</view>

为了解决这个问题,我收集到一些<template/>的写法:

  • <template is="msgItem" data="{{'这是一个参数'}}"/>
  • <template is="t1" data="{{newsList, type}}"/> 【目前支持转换的写法】
  • <template is="head" data="{{title: 'action-sheet'}}"/> 【目前支持转换的写法】
  • <template is="head" wx:if="{{index%2 === 0}}" data="{{title: 'action-sheet'}}"/> 【目前支持转换的写法】
  • <template is="courseLeft" wx:if="{{index%2 === 0}}" data="{{...item}}"></template>
  • <template is="{{index%2 === 0 ? 'courseLeft' : 'courseRight'}}" data="{{...item}}"></template>
  • <template is="stdInfo" wx:for="{{stdInfo}}" data="{{...stdInfo[index], ...{index: index, name: item.name} }}"></template>

目前仅针对第二、三、四种写法可以实现完美转换。而其它写法,目前uni-app并不支持v-bind=""和动态组件语法,暂无法支持。
如有大佬对此有完美解决方案,请不吝赐教,谢谢~~

目前的处理规则:

  1. 将wxml里<tempate name="abc">内容提取,生成vue文件,并注册为全局组件
  2. <template is="head" data="{{title: 'action-sheet'}}"/>转换为```<component :is="head" title="'action-sheet'"`/>``
  3. 删除<import src="../../../common/head.wxml" />
  4. 因uni-app暂时还不支持动态组件,导致:is="xxx"这种语法并不能支持,为保证转换后能跑起来,已经屏蔽相关代码,且写入日志,方便查看

wxParse不支持转换

建议手动替换为插件市场里的wxParse

wxaSortPicker不支持转换

建议手动替换为插件市场里的wxaSortPicker

变量名与函数名重名

报错:[Vue warn]: Method "xxx" has already been defined as a data property. 解决:在小程序里,data里变量与函数可以同名,而在vue里当场报错,需手动将函数名重名,并修改template里所绑定的函数名。

未在data里声明,而直接使用setData赋值

报错:Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option. 解决:工具尽可能的收集了页面里的setData({})里的参数,与data里的变量进行对比,并添加,一般情况不会报这个错。出现这个错,可能是页面里将this传到其他文件里,并调用了setData()函数导致的,需手动修改。

使用别名代替this,导致this.data.xxx没法替换

报错: Cannot read property 'xxx' of undefined
解决:可能是使用了o、a、i、e等变量缓存了this,导致工具没法转换o.data.xxx为o.xxx。
btw:碰到一个源码就是这种单个字符,应该是被工具压缩过代码。
目前工具已经支持转换的变量关键字为:
this.data.xxx ==> this.xxx
that.data.xxx ==> that.xxx
self.data.xxx ==> self.xxx
_.data.xxx ==> _.xxx
_this.data.xxx ==> _this.xxx

include标签

include标签不是蛮好转换,看过几份源代码,仅有一份代码里,使用了它。 建议手动将内容拷贝进来。

wx:if="{{}}"

遇到这种,建议手动修复

main.js加入的组件,里面包含getApp()

遇到这种,建议手动修复,因为main里加载的时候,还没有getApp()

<view @tap="delete"/>

编译报错:语法错误: Unexpected token
这种在uni-app里没法编译过去
因未能找到关键字列表及相关文档,建议手动重名(工具针对delete已经处理)

var appInstance = getApp();

建议手动处理

运行wtu -V报错

$ wtu -v
/usr/local/lib/node_modules/miniprogram-to-uniapp/src/index.js:297
async function filesHandle(fileData, miniprogramRoot) {
^^^^^^^^
SyntaxError: Unexpected token function
......
原因:当前nodejs版本不支持es6语法
解决:升级nodejs版本,建议v9以上

语法错误: This experimental syntax requires enabling the parser plugin: 'dynamicImport'

可能是函数名使用了系统保留关键字,如<input @input="import"></input>
暂时建议手动处理一下,毕竟还只遇到一例

this.setData(result.data)

建议手动处理,这类匿名传值的操作

require('./bem.wxs')

uni-app暂不支持在 wxs、sjs、filter.js 中调用其他同类型文件,建议手动处理

更新记录

v1.0.26(20191013)

  • [修复] wx:key="this"这种情况
  • [修复] 删除vue.config.js里的css节点
  • [修复] 识别含VantComponent({})的js文件
  • [修复] 未知原因导致没有生成main.js的bug
  • [修复] app.json不存在导致没有生成main.js的bug
  • [修复] app.js里非生命周期函数没有放到globalData里的bug
  • [修复] style="{{bgImage?'background-image:url('+bgImage+')':''}}"这种情况
  • [修复] wx:for="item in 12"识别出错的bug(wx:for里包含in,第一次在小程序里见到这种写法)
  • [优化] wxs引入方式为script标签引用
  • [优化] 替换stringToObject()为object-string-to-object

v1.0.25(20190928)

  • [新增] 处理一则代码非常规写法(没法描述……类似:Page((_defineProperty(_Page = {})))
  • [修复] 优化函数与data里变量重名,导致编译报错的bug(重名的函数名在后面添加后缀Fun,如abc() --> abcFun())
  • [修复] 不复制index.json到生成目录
  • [修复] 完善pages.json页面的style(之前只写了标题,这次将页面属性都写入)
  • [修复] 当attr={{true}}或attr={{false}},则不添加v-bind(如<scroll-view scroll-x="{{false}}"/>)
  • [修复] 替换style="xx:'{{}}'" --> style="xx:{{}}"
  • [修复] 替换style="background-image: url('{{iconURL}}/abc.png')" --> style="background-image: url({{iconURL}}/abc.png)"
  • [修复] 当单个js或wxss内容为空时,也创建相应文件,防止编译报错。
  • [修复] style里包含表达式时(+-*/和三元表达式),使用括号包起来(如style="height:{{info.screenHeight * 105}}px")
  • [修复] 解析前替换掉"export default App;",防止干扰,导致app.js没有转换成功
  • [修复] wx:key="{{item}}"转换为:key="item"的bug
  • [修复] 转换<view style="display:{{}}"></view>时末尾为+的bug
  • [修复] wxml里template连环嵌套引用,导致生成vue代码时template为空的bug
  • [修复] app.js已含globalData,导致重复嵌套的bug
  • [修复] app.js已含data时,移入到globalData
  • [修复] app.js,支持替换that.globalData.xx为that.$options.globalData.xxx
  • [修复] app.js里所有移动到globalData里的函数及变量的引用关系
  • [修复] app.js里getApp().data.xxx -- this.$options.globalData.xxx
  • [修复] app.js引用的组件,初始化时getApp()为undefined的bug
  • [修复] 外部定义的含require()的变量里的路径(如:var md5 = require('md5.js'))
    规则:
    1.删除var app = getApp()或const app = getApp(),作用:不让一加载就引用getApp()
    2.app.globalData.xxx --> getApp().globalData.xxx
    2.app.xxx --> getApp().globalData.xxx
    4.getApp().xxx --> getApp().globalData.xxx
    5.var icon_url = app.dataBase.iconURL; --> var icon_url = getApp().globalData.dataBase.iconURL;
    6.getApp().globalData.xxx保持原样
    注意:如外部定义的变量引用了getApp(),仍会报错,需手动修复

v1.0.24(20190918)

  • [新增] 支持wx-if转换(对,你没看错,wx:if和wx-if都能用……)
  • [新增] 支持wx:else="{{xxx}}"转换
  • [新增] 支持subPackages分包加载
  • [新增] 识别app.js里exports.default = App({});结构
  • [新增] 识别js文件是否为vue文件结构,通过结构export default {}识别
  • [新增] 增加_.data.xxx转换为_.xxx(定义_为this副本)
  • [新增] 忽略组件plugin:/calendar转换
  • [新增] 收集页面里setData()里参数与data里的变量进行对比,并将差异增加到data里,尽可能修改因未定义变量而直接使用setData()报错的问题(无法100%修复,详见“关于不支持转换的语法说明”)
  • [修复] 修复json文件里定义的usingComponents路径转换
  • [修复] 修复app.json里tabbar里的路径转换
  • [修复] 修复因为找不到<template is="abc"/>这里面的abc组件,而出现undefined.vue组件的bug
  • [修复] app.js里,所有非生命周期函数或变量,均放入到globalData里
  • [修复] var app = getApp(); 替换为 var app = getApp().globalData;
  • [修复] 目前uni-app对于非H5平台,暂无法支持动态组件。因此,转换时,将显式引用的组件使用转换为显式组件引用(如<template is="abc"/>),隐式声明的组件(如<template is="{{item.id}}"/>),暂时无法支持,为了保证转换后能正常运行,将直接注释,并存入转换日志,方便后续修改。
  • [修复] css由"内嵌"改为import方式导入,防止vue文件代码行数过长

v1.0.23(20190907)

  • [修复] @tap前面被添加冒号的bug
  • [修复] app.js没有被转换的bug
  • [修复] 当解析js报错时(如js里使用了重载),将返回原文件内容

历史更新记录已移入ReleaseNote.md

感谢

参考资料

  1. [AST实战]从零开始写一个wepy转VUE的工具 此文获益良多
  2. https://astexplorer.net/ AST可视化工具
  3. Babylon-AST初探-代码生成(Create) 系列文章(作者是个程序媛噢~)
  4. Babel 插件手册 中文版Babel插件手册
  5. Babel官网 有问题直接阅读官方文档哈
  6. 微信小程序转换uni-app详细指南 补充了我一些未考虑到的规则。

最后

如果觉得帮助到你的话,点个赞呗~

打赏一下的话就更好了~

微信支付支付宝支付

LICENSE

This repo is released under the MIT.

About

Try to transform Weixin miniprogram project to Uni-app project

License:MIT License


Languages

Language:JavaScript 96.3%Language:Vue 2.9%Language:HTML 0.8%