likes
comments
collection
share

移动端多平台 Taro 跨端开发总结(一)

作者站长头像
站长
· 阅读数 12

一、项目的业务含义

三个比较重大的含义:

  • 代码复用,不用再前端、客户端自己分别实现,不再存在多套业务代码,维护简单
  • 前端与客户端人员能协同合作开发业务需求,大前端嘛!(简单来讲就是 “开猿节流” ...
  • 支持多平台多端的业务扩展,能够实现打包不同平台的代码(eg. 抖音小程序)进行流量投放进行引流


二、Taro 框架跨端的使用与限制性

2.1 样式管理

React Native 与一般 Web 样式支持度差异较大,web 与小程序端支持的 CSS 样式能力比 RN 大得多。样式上 H5 最为灵活,小程序次之,RN 最弱,统一多端样式即是对齐短板,也就是要以 RN 的约束来管理样式,同时兼顾小程序的限制,核心可以用三点来概括:

  • 使用 Flex 布局
  • 基于 BEM 写样式
  • 采用 style 属性覆盖组件样式

布局与定位

1.1. diaplay 布局:

RN 下仅支持 flex 布局;web 与小程序端则正常布局属性;

  • RN 所有元素节点都是自带 display: flex; 而 web 与小程序则无该限定,因此极度容易漏了这个默认样式的处理;
  • 如果要使用特殊布局则需要进行平台判断处理,可以封装为 scss 的 mixin 方法;

1.2. position 定位:

RN 下默认为 relative,支持 absolute;web 与小程序端则正常定位属性;

  • RN absolute 绝对定位是面的标签覆盖展示在前面定义的标签中,与 z-index 与 relative 层级无关;
  • 如果要使用特殊定位则需要进行平台判断处理,可以封装为 scss 的 mixin 方法;
  • 吸顶:web 与 小程序能使用 sticky;RN 需要使用 ScrollView 的 stickyItemIndex 属性配置第几个吸顶

2.2 样式编写的限制

1. 编写 BEM 样式

目前在 Taro 项目当中使用的样式是 css modules 的形式,因此如果多个组件当中使用了相同的 class 名就有可能发生同名 class 的样式覆盖的问题,因此需要使用一个统一的规范对不同组件的样式进行一个区分,这里团队选用的规范是 BEM。

2. 样式的限制

  • 在小程序与 web 端当中并无过多的样式类及样式选择器的限制(如伪类、兄弟节点选择器、首个、最后一个等选择器;),但是在 RN 端下相关的一些花里胡哨的选择器是不生效甚至会存在语法报错的......
  • RN 当中还限制了父子选择器这种语法的使用不生效,因此基本都是使用 BEM 规范来写仅有一层的样式类。

3. 组件的样式覆盖

想要在组件外对组件内部样式进行覆盖的情况,在跨端当中透传 class 会存在着奇奇怪怪的问题,例如 RN 端是不会对相关样式进行覆盖处理。

// 目前 Taro RN 端还未实现往组件传递 className 对应样式
<CompA compClass='my-style' />

// CompA,样式不生效
<View className={this.props.compClass} />

因此想要在组件外对组件内部样式进行覆盖使用内联的 style 方式是相对方便、兼容性好的方式。

  • 需要注意一点,样式文件是会经过编译处理兼容多端的,但 style 方式需要运行时兼容:background/backgroundColor

这个角度上,又回到了前面提到的样式形式问题,最好使用的方案应该是 CSS-in-JS(styled-compoment),但是很可惜,Taro 目前还不支持(好像是因为小程序端的原生的不支持的限制)。

2.3 多端样式兼容

1. 单位适配:

这里使用的是 Taro 默认的方案(只管写 px 单位,taro 会根据不同平台和配置的转换对应平台的单位和数值)。

  • RN 是 px、H5 是 rem、小程序是 rpx。

taro-docs.jd.com/docs/size

这里 Taro 的底层是使用了 postcss 的一个二开插件postcss-pxtransform来进行不同编译平台的单位与数值的转换:

www.npmjs.com/search?q=po…

2. 平台区分:

在 taro 当中,已经对不同的编译平台之间会存在差异进行提供样式编写条件编译的 API 扩展了,Taro 对 postcss 进行了扩展并且封装为 npm 插件postcss-crossplatformcomments来注入相关的平台环境变量,这样子就能在 scss 当中根据平台判断来编写一些平台的特殊样式代码以及扩展 mixin 的能力适配多端:

www.npmjs.com/package/pos…

  • ifdef:编译相关平台时候生效
  • ifndef:编译相关平台时候需要过滤
// 这里简单演示一下相关的用法

.safe-area {
  /* #ifdef h5 weapp tt */
  @include safe-area();
  /* #endif  */
}

@mixin box-sizing($val) {
  /* #ifndef rn */
  box-sizing: $val;
  /* #endif */
}

ps:但是可惜的是,这个官方提供平台判断仅限于编译的各个平台值,还没具体划分到 ios 还是 android 这两种不同机型平台划分的粒度差异,因此在安卓和 ios 有差异的情况下,目前的解决办法还是只能通过 api 判断出具体的机型,然后赋值不同的 style 或者 class 样式类进行对样式差异的处理。

2.4 端能力的差异

相较于样式,端能力的差异倒是还好,各端差异是客观存在的,更不用说 RN 在 iOS 与 Android 上就已存在大量差异。

应对端能力差异,要么改变实现思路,例如 RN 端还不支持 Taro.(get/set)StorageSync,那就改用 async / await + Taro.(get/set)Storage 实现,要么就得使用环境判断方式了。

2.5 环境变量判断区分

Taro 提供 process.env.TARO_ENV 用于环境判断

function foo() {
  if (process.env.TARO_ENV === 'weapp') {
    // 微信小程序逻辑
  }
  if (process.env.TARO_ENV === 'h5') {
    // H5 逻辑
  }
  if (process.env.TARO_ENV === 'rn') {
    // RN 逻辑
  }
}

2.6 条件编译文件

在 Taro 当中提供了另一种能编写针对跨端不同平台差异的写法,使用不同平台的后缀名来进行区分平台的条件编译与引入。

/components
	|--/test
  		|--index.js // 保底通用
      |--index.rn.js
  		|--index.h5.js
  		|--index.weapp.js
	|--xxx
// 例如原先有一个组件 test.js
// 若需要分别实现 h5 端、RN 端的组件,则将相应组件命名为:
// index.h5.js,index.rn.js
// 这样只需要引入 test,Taro 会根据环境自动引入相应的组件
// 就不需要写 process.env.TARO_ENV 的判断了
import Test from '../../components/test'

render() {
    // 例如编译 h5 时,实际引入的组件是 test.h5.js
    // 组件只需要遵循对外接口统一即可
    return <Test data={data} onClick={onClick} />
}


三、旧项目的跨端过渡与统一

App 端的过渡:

  • 主应用还是原生,使用 Taro RN 编译出来的页面则是原生 App 通过一个容器进行加载处理(可以理解就是 MPA 的形式);
  • 因此有些生命周期其实需要 App native 进行一个桥接调用,并且每个页面因为是 MPA 的加载形式,有不少的启动逻辑、变量在当前的过渡期会重复执行;
小程序 端的过渡:
  • Taro 项目打包混合包,然后原架构的小程序通过分包引入的相对独立的 taro 项目
  • 若是主 tab 的页面的情况则是主包同时承载着两个框架并存
  • 通过 gulp 脚本来对项目的 app.json 文件进行相关页面的配置注入操作;
  • 直到能够将主包的页面都迁移到新的 Taro 项目当中,此时是反向的操作:Taro 构建出自己的主包和分包后再将原框架编译出来的页面作为一个单独的分包合并到 Taro 构建出来的产物当中(文件迁移与app.json进行页面配置注入)
H5 端的过渡:
  • 新项目的页面其实相对独立,配置好相关转跳和参数即可。
  • 对于曾经分享的链接,简单的兼容处理则进行一个页面的重定向即可。


受限于篇幅和相关的内容模块划分和组织上面,这期就先和大家分享下 taro 在多端开发当中对多端平台上的适配方面的基础。下一期我们接着进一步对项目当中的对多端实际运行差异的总结与相关差异组件的封装处理的介绍。