原生小程序转 Taro 代码有什么需要注意的吗?



  • v1.2.0 开始支持此功能

    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.datathis.properties

    this.datathis.properties 相当于 Taro 的 this.statethis.props 的 alias,当它们的数据更新时,对应的 stateprops 也会同步更新。

    生命周期

    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 嵌套。

    不支持 relationsBehavior

    目前转换暂只支持转换 PageComponentApp 三种构造器创造的小程序组件实例。 relationsBehavior 在其他许多小程序端中还没有对应的实现,我们认为实现这两个功能意义不大。

    转换 wepy 文件不成功

    目前只能支持转换使用原生微信小程序开发的应用。



  • 你们认为意义不大。 但是我们怎么知道 那些小程序可以转,那些不能转呢?



  • @smartchina1977 这里作者的意思应该是说,转 Taro 大多是为了多端的需求,relationsBehavior 在其他许多小程序端中还没有对应的实现,所以没有意义。但这里还有一个问题,想改成 Taro 写法来写微信小程序应该是有意义的,不过 Taro 也是支持混写的,所以表述为意义不大吧。


登录后回复