微信小程序轉Taro (轉發https://nervjs.github.io/taro/docs/taroize.html)
Taro 可以將你的原生微信小程序應用轉換為 Taro 代碼,進而你可以通過 taro build 的命令將 Taro 代碼轉換為對應平台的代碼,或者對轉換后的 Taro 代碼進行用 React 的方式進行二次開發。
微信原生小程序轉 Taro 的操作非常簡單,首先必須安裝使用 npm i -g @tarojs/cli 安裝 Taro 命令行工具,其次在命令行中定位到小程序項目的根目錄,根目錄中運行:
$ taro convert
即可完成轉換。轉換后的代碼保存在根目錄下的 taroConvert 文件夾下。你需要定位到 taroConvert 目錄執行 npm install 命令之后就可以使用 taro build 命令編譯到對應平台的代碼。
二次開發
假設已有一個轉換后文件如下:
import { View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import withWeapp from '@tarojs/with-weapp'
import './index.scss'
var app = Taro.getApp()
@withWeapp('Page')
class _C extends Taro.Component {
state = {}
componentWillMount(e) {
var orderId = e.id
this.data.orderId = orderId
}
componentDidShow() {
var that = this
Taro.request({
url: 'https://api.it120.cc/' + app.globalData.subDomain + '/order/detail',
data: {
token: Taro.getStorageSync('token'),
id: that.data.orderId
},
success: res => {
Taro.hideLoading()
if (res.data.code != 0) {
Taro.showModal({
title: '錯誤',
content: res.data.msg,
showCancel: false
})
return
}
that.setData({
orderDetail: res.data.data,
logisticsTraces: res.data.data.logisticsTraces.reverse()
})
}
})
}
config = {
navigationBarTitleText: '物流詳情'
}
render() {
const {
orderDetail: orderDetail,
logisticsTraces: logisticsTraces
} = this.state
return (
<View className="container">
<View className="top-sec">
<View className="a-row">
<View className="label">物流單號</View>
<View className="text">{orderDetail.logistics.trackingNumber}</View>
</View>
<View className="a-row">
<View className="label">物流公司</View>
<View className="text">{orderDetail.logistics.shipperName}</View>
</View>
</View>
<View className="sec-wrap">
<View className="details-info">
<View className="line-box" />
{logisticsTraces.map((item, index) => {
return (
<View className="a-row" key={index}>
<View className="dot">
<View
className="active-dot"
hidden={index == 0 ? false : true}
>
<View className="yuan-red" />
</View>
<View
className="default-dot"
hidden={index == 0 ? true : false}
/>
</View>
<View className="info">
<View className="date-box">{item.AcceptTime}</View>
<View className="text">{item.AcceptStation}</View>
</View>
</View>
)
})}
</View>
</View>
</View>
)
}
}
export default _C
它看起來就像普通的 Taro 組件,最重要的區別就在於 @withWeapp() 這個裝飾器,你可以將它理解為轉換代碼的運行時,@withWeapp() 會增加一些原來 Taro 沒有方法和屬性,例如:
this.setData
轉換后的 this.setData 的 API 相當於小程序的 this.setData 的 polyfill,他和 this.setState 最大的區別就在於,this.setData 之后 data 的數據是同步更新,而渲染是異步更新,而 setState 兩者都是異步的。
this.data 和 this.properties
this.data 和 this.properties 相當於 Taro 的 this.state 和 this.props 的 alias,當它們的數據更新時,對應的 state 和 props 也會同步更新。
生命周期
Taro 會將原始文件的生命周期鈎子函數轉換為 Taro 的生命周期,完整對應關系如下:
| Page.onLoad | componentWillMount |
|---|---|
| onShow | componentDidShow |
| onHide | componentDidHide |
| onReady | componentDidMount |
| onUnload | componentWillUnmount |
| onError | componentDidCatchError |
| App.onLaunch | componentWillMount |
| Component.created | componentWillMount |
| attached | componentDidMount |
| ready | componentDidMount |
| detached | componentWillUnmount |
| moved | 保留 |
常見問題
在小程序 IDE 顯示 _createData 錯誤
這個錯誤通常是由於原始代碼的初始 data 中沒有對應的數據,后來通過 this.setData 補充數據造成的。在 Taro 中推薦不管是 state(data) 還是 properties(props) 都要設置一個默認值。你可以在類構造器或修改原始代碼提供一個默認值解決這個問題,這也應該是編寫代碼的最佳實踐。
轉換 wxParse 報錯不存在文件
這是由於 wxParse 的源碼使用了一個不存在的 template 聲明造成的。你可以修改 wxParse 的源碼文件 wxParse.wxml 134 行到 207 行:
<!--循環模版--> <template name="wxParse1"> <!--<template is="wxParse1" data="{{item}}" />--> <!--判斷是否是標簽節點--> <block wx:if="{{item.node == 'element'}}"> <block wx:if="{{item.tag == 'button'}}"> <button type="default" size="mini"> <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key=""> <template is="wxParse0" data="{{item}}" /> </block> </button> </block> <!--li類型--> <block wx:elif="{{item.tag == 'li'}}"> <view class="{{item.classStr}} wxParse-li" style="{{item.styleStr}}"> <view class="{{item.classStr}} wxParse-li-inner"> <view class="{{item.classStr}} wxParse-li-text"> <view class="{{item.classStr}} wxParse-li-circle"></view> </view> <view class="{{item.classStr}} wxParse-li-text"> <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key=""> <template is="wxParse0" data="{{item}}" /> </block> </view> </view> </view> </block> <!--video類型--> <block wx:elif="{{item.tag == 'video'}}"> <template is="wxParseVideo" data="{{item}}" /> </block> <!--img類型--> <block wx:elif="{{item.tag == 'img'}}"> <template is="wxParseImg" data="{{item}}" /> </block> <!--a類型--> <block wx:elif="{{item.tag == 'a'}}"> <view bindtap="wxParseTagATap" class="wxParse-inline {{item.classStr}} wxParse-{{item.tag}}" data-src="{{item.attr.href}}" style="{{item.styleStr}}"> <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key=""> <template is="wxParse0" data="{{item}}" /> </block> </view> </block> <block wx:elif="{{item.tag == 'table'}}"> <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}"> <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key=""> <template is="wxParse0" data="{{item}}" /> </block> </view> </block> <block wx:elif="{{item.tag == 'br'}}"> <template is="WxParseBr"></template> </block> <!--其他塊級標簽--> <block wx:elif="{{item.tagType == 'block'}}"> <view class="{{item.classStr}} wxParse-{{item.tag}}" style="{{item.styleStr}}"> <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key=""> <template is="wxParse0" data="{{item}}" /> </block> </view> </block> <!--內聯標簽--> <view wx:else class="{{item.classStr}} wxParse-{{item.tag}} wxParse-{{item.tagType}}" style="{{item.styleStr}}"> <block wx:for="{{item.nodes}}" wx:for-item="item" wx:key=""> <template is="wxParse0" data="{{item}}" /> </block> </view> </block> <!--判斷是否是文本節點--> <block wx:elif="{{item.node == 'text'}}"> <!--如果是,直接進行--> <template is="WxEmojiView" data="{{item}}" /> </block> </template>
把 <template name="wxParse1"> 的模板內所有 <template is="wxParse2" data="{{item}}" /> 修改為 <template is="wxParse0" data="{{item}}" /> 再運行 taro convert 即可。這樣修改之后還會取消原來 wxParse 只能處理 11 級 HTML 嵌套的問題,理論上內存不爆棧可以處理無限級 HTML 嵌套。
不支持 relations 和 Behavior
目前轉換暫只支持轉換 Page、Component 、App 三種構造器創造的小程序組件實例。 relations 和 Behavior在其他許多小程序端中還沒有對應的實現,我們認為實現這兩個功能意義不大。
轉換 wepy 文件不成功
目前只能支持轉換使用原生微信小程序開發的應用。
