输入小程序项目路径,输出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,并注册为全局组件
- [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] 转换前先格式化代码
常规我们见到的代码是这样的(摘自官方小程序示例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=""和动态组件语法,暂无法支持。
如有大佬对此有完美解决方案,请不吝赐教,谢谢~~
目前的处理规则:
- 将wxml里
<tempate name="abc">
内容提取,生成vue文件,并注册为全局组件 - 将
<template is="head" data="{{title: 'action-sheet'}}"/>
转换为```<component :is="head" title="'action-sheet'"`/>`` - 删除
<import src="../../../common/head.wxml" />
- 因uni-app暂时还不支持动态组件,导致:is="xxx"这种语法并不能支持,为保证转换后能跑起来,已经屏蔽相关代码,且写入日志,方便查看
建议手动替换为插件市场里的wxParse
建议手动替换为插件市场里的wxaSortPicker
报错:[Vue warn]: Method "xxx" has already been defined as a data property. 解决:在小程序里,data里变量与函数可以同名,而在vue里当场报错,需手动将函数名重名,并修改template里所绑定的函数名。
报错: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()函数导致的,需手动修改。
报错: 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标签不是蛮好转换,看过几份源代码,仅有一份代码里,使用了它。 建议手动将内容拷贝进来。
遇到这种,建议手动修复
遇到这种,建议手动修复,因为main里加载的时候,还没有getApp()
编译报错:语法错误: Unexpected token
这种在uni-app里没法编译过去
因未能找到关键字列表及相关文档,建议手动重名(工具针对delete已经处理)
建议手动处理
$ 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以上
可能是函数名使用了系统保留关键字,如<input @input="import"></input>
暂时建议手动处理一下,毕竟还只遇到一例
建议手动处理,这类匿名传值的操作
uni-app暂不支持在 wxs、sjs、filter.js 中调用其他同类型文件,建议手动处理
- [修复]
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
- [新增] 处理一则代码非常规写法(没法描述……类似: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(),仍会报错,需手动修复
- [新增] 支持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文件代码行数过长
- [修复] @tap前面被添加冒号的bug
- [修复] app.js没有被转换的bug
- [修复] 当解析js报错时(如js里使用了重载),将返回原文件内容
- 感谢转转大佬的文章:[AST实战]从零开始写一个wepy转VUE的工具,* 本项目基于此文章里面的代码开发,在此表示感谢~
- 感谢网友[没有好名字了]给予帮助。
- 感谢官方大佬DCloud_heavensoft的文章:微信小程序转换uni-app详细指南,补充了我一些未考虑到的规则。
- this.setData()代码出处:https://ask.dcloud.net.cn/article/35020,在些表示感谢~
- 感谢为本项目提供建议以及帮助的热心网友们~~
- [AST实战]从零开始写一个wepy转VUE的工具 此文获益良多
- https://astexplorer.net/ AST可视化工具
- Babylon-AST初探-代码生成(Create) 系列文章(作者是个程序媛噢~)
- Babel 插件手册 中文版Babel插件手册
- Babel官网 有问题直接阅读官方文档哈
- 微信小程序转换uni-app详细指南 补充了我一些未考虑到的规则。
如果觉得帮助到你的话,点个赞呗~
打赏一下的话就更好了~
This repo is released under the MIT.