背景

UU跑腿小程序作为公司的主要流量入口,对公司的业务发展起到了很大的推动作用。目前我们已在微信、支付宝、百度、抖音、高德平台上架小程序。而随着公司业务的发展,目前的Taro2版本内置的平台已无法支持我们的业务需求。而自Taro3.0后支持了开发式插件系统,可以让开发者根据自己的业务需求去扩展平台,且更好的跨框架特性等,都值得我们去拥抱Taro3.0。本文主要介绍taro升级过程中出现的问题及解决方案。

原始版本:Taro2.2.26
升级版本:Taro3.3.12 + React17.0.0 + Redux4.0.0
参考文档: 【官方迁移指南】

目录

  • 背景
  • 升级问题
  • 更新项目依赖
  • 配置文件
  • 启动项目
  • 获取路由参数
  • render函数
  • redux
  • 其他
  • SourceMap 支持
  • 平台兼容

升级问题

建议优先阅读官方迁移指南指南中已对升级步骤做了详细的介绍,此文主要针对升级过程中存在的问题进行说明。

1. 更新项目依赖

官方文档中是直接更项目依赖的,但实际升级过程中,由于项目依赖包较多,且依赖版本无法是否应该升级,故建议新建项目,然后在新项目的基础上进行增量的添加自己项目包;

# 更新Cli
$ npm i -g @tarojs/cli@next
# 新建项目
$ taro init myApp  
# 复制新项目的package.json文件覆盖当前项目的package.json(注意做好备份),
$ npm i xxx # 添加自己项目的依赖包

2. 配置文件

建议直接使用新项目的配置文件(config/**, 可直接复制文件夹),并在此基础上做针对项目的配置文件修改。

image.png

3. 启动项目

如果已参考官方指南完成了所有迁移工作,此时就可以尝试启动项目了,但启动的过程中可能会有很多的错误,那就需要根据控制台报错信息边改边启动了,一般的错误还是比较明显的。但有个样式报警(如下图),需要修改配置文件。
image.png

这个是因为多个文件引入了相同的样式文件,但是引入顺序不一样,可在配置文件中config/index.js配置忽略即可。

const config = {
   mini: {
      miniCssExtractPluginOption: {
         ignoreOrder: true, // 忽略引入样式文件的顺序 
      },
   }
}

4. 获取路由参数

Taro3.3版本在获取参数的时候存在Taro.getCurrentInstance().router 结果为null的情况(onShow中情况较多),目前Taro社区中暂无解决方案,此处建议做兼容处理。目前我们采取的处理办法如下,但如果有更好的办法,还望分享。

# 封装统一的获取路由参数的方案
const getTaroParams = (instance) => {
   let params = {};
   let ins = instance || Taro.getCurrentInstance();
   try {
     if(ins && ins.router) {
        params = ins.router.params
     } else {  // 如果获取不到,从历史路由中获取
     let pages = Taro.getCurrentPages(); 
     let thisPage = pages[pages.length - 1]; 
     if(thisPage && thisPage.options) {
        params = thisPage.options;
     }
  }
} catch (err) { console.log(err)}
   return params || {};
}
# -----------------页面调用 -------------------
class Page extends Component {
  $instance = Taro.getCurrentInstance();

  # 方法调用
  componentDidShow() {
    const params = getTaroParams(this.$instance);
  }
}

5. render函数

在Taro2中的render方法中,taro框架为我们做了很多错误语法的兼容处理,但是升级Taro3中,所有的问题就一一暴露了出来。

5.1 组件引入

老版本中页面render函数中用的的组件是不需要引入的,页面也并不会报错,但是新版中所有的组件就必须一一引入,否则就会报错

image.png

需在顶部引入

import { Swipper } from '@tarojs/components'

5.2 为空判断

页面中用到的变量必须做非空判断,框架不再做兼容

<View>{ userInfo?.userName }</View>

5.3 &&逻辑

很多时候,我们会写如下代码

list.length && <View>...</View>

但在新版的项目中,如果list为空数组,此处展示在页面上则为’0’, 即需要确保&&之前的变量或表达式必须是布尔类型。如遇此情况,可做以下修改

Boolean(list.length) && <View>...</View>

5.4 bind(this)

Taro2中,如果render中调用的方法没有bind(this), 也是可以直接调用的,但是Taro3就必须bind(this)

<View onClick={this.onSave.bind(this)}></View>
# OR
onSave = () => {
  ....
}

5.5获取页面元素

理论上我们再DidMount中获取元素是没有问题的, 但实际情况可能跟我们想想的不一样,经常会获取不到元素,如遇到此问题,建议做异步处理Taro.nextTick(() => {} )

class C extends Component { 
   componentDidMount() {
     Taro.nextTick(()=> {
         const query = Taro.createSelectorQuery().in(Taro.getCurrentInstance().page)
         query.select('#pick-bar').boundingClientRect(res => { 
           ...
         }
      }).exec()
     }
  }
  redner() {
     return <Viev id="pick-bar"></View>
  }
}

5.6 hidden失效

# 此处失效
<View  hidden={isShow}></View>
# 改为
{  isShow && <View></View>  }

5.7 组件内部元素添加Id

有时候我们会在通过props传入组件内部Id(但并不建议在公共组件中通过外部传入id), 但如果存在相同的id, 或者id为空,会导致点击事件混乱,而且如果组件嵌套层级很深的话,很难发现此问题。

class C extends Component {
   render() {
      let id = this.props.id; # 如果id为空或者id相同,会造成页面点击混乱
      return <View id={id}></View>
   }
}

6. redux

在Taro2中, connect函数中的mapDispatchToProps会默认传入dispatch, 但Taro3中,不再做支持, 需要自己添加返回, 如下所示:

class C extends Component {
  ...
  onSave() {
    let { dispatch } = this.props;
    dispatch({ type: 'app/save'})
  }
  ...
}
const mapDispatchToProps = dispatch => {
   return {
     dispatch, # 需自己添加
     update: (state) => dispatch.app.updateSate(state)
   }
}
export default connect(mapStateToProps, mapDispatchToProps)(C)

其他

1. SourceMap支持

Taro2中并不支持SourceMap, 导致在平台的错误日志中根本无法定位错误位置,但在Taro3中新增了对SourceMap的支持,如需使用,可在config/index.js中做如下配置

const config = {
  mini: {
    enableSourceMap: true,
    sourceMapType: 'source-map',
   }
}

支持后的错误信息如下图所示

image.png

2. 平台兼容

2.1 百度

对于Taro3的多平台支持,微信、支付宝、抖音的支持度与Taro2差别不大,但Taro3的百度小程序flex布局存在诸多问题,尽管Taro官方说已做优化,但问题依然存在,在论坛上看有人提出的一个解决办法, 尝试后发现能解决大部分flex布局的问题。

# 在src/app.scss(.css)中加入此全局样式
swan-template {
  display: contents;
}

但除此之外,百度依然有很多样式兼容问题,并未一一解决,建议对不兼容的样式,可尝试做降级处理。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注