taro跨端开发之平台化代码分类

338 阅读2分钟

目前taro涉及到了微信小程序(weapp),支付宝小程序(alipay)和h5端的开发,每个端都有自己的独有组件,生命周期和系统api,但很多地方其实都公用的。支付宝原生和微信原生本身有很多共通的地方,用了taro之后,大部分组件,api更是用一套即可实现。

命名规则

taro编译的时候会根据后缀编译成不同平台的文件,比如有一个test.js文件

test.alipay.js 支付宝小程序文件

test.weapp.js 微信小程序文件

test.h5.js h5文件

不定义的话默认使用test.js文件,引用时不需要加后缀,直接使用 import * from 'test'

因为上述规则,文件命名时不需要额外加上平台标识,比如 alipayTest.js是不正确的

平台差异化代码

如果渲染的一些样式根据不同平台有差异化,建议抽成组件,如下所示

// bad
isWeapp ? (
	<View>我是微信</View>
) : isAlipay ? <Image src='https://xxx.png' /> : null

// better
// name.alipay.js
<Image src='https://xxx.png' />
// name.weapp.js
<View>我是微信</View>

<Name />

但是有些情况下,可能不需要抽成组件,而只要维护一个变量或者方法即可,如下所示

// bad
isWeapp ? (
	<View>我是微信</View>
) : isAlipay ? <View>我是支付宝</View> : null

// good
// name.alipay.js
<View>我是支付宝</View>
// name.weapp.js
<View>我是微信</View>

<Name />

// better
const env = process.env.TARO_ENV
const platformName = {
	'alipay': '支付宝',
	'weapp': '微信'
}
<View>我是{platformName[env]}</View>

看到这两者的差异了吗?当然用第一种方法是万能的,不管以后有多少平台都可以无侵入扩展,第二种就需要修改代码,但是因为有公共的部分,也更容易维护。

所以是否需要抽成组件看不同平台的组件相似度

组件封装

某些taro组件或者引入的第三方组件并非跨平台支持,比如taro中的OpenData,目前只支持微信小程序,那么我们可以再封装一个自己的OpenData来跨平台支持。

在components下建open-data目录,在目录下新建两个跨平台文件,index.weapp.js和index.alipay.js。

index.weapp.js文件内容如下

export { OpenData } from '@tarojs/components'

因为taro本身就支持,所以直接导出taro组件

index.alipay.js需要自己封装

import { useSelector } from 'react-redux'
import { View, Image } from '@tarojs/components'

import './index.scss'

// type以小程序类型为准 [https://developers.weixin.qq.com/miniprogram/dev/component/open-data.html]
export function OpenData(props) {
  const { type, emptyValue = {} } = props
  const { emptyNickName = '未登录', emptyGender = '未知', emptyAvatar } = emptyValue

  const { nickName, gender, avatar } = useSelector(e => e.user)

  let dom = null

  if (type === 'userNickName') {
    dom = <View>{nickName || emptyNickName}</View>
  }

  if (type === 'userGender') {
    dom = <View>{gender || emptyGender}</View>
  }

  if (type === 'userAvatarUrl') {
    dom = (avatar || emptyAvatar) ? (
      <Image className='image' src={avatar || emptyAvatar} />
    ) : (
      <View className='imageEmpty' />
    )
  }

  return (
    <View className='authBtn'>
      {dom}
    </View>
  )
}

这里看到根据不同的type来返回不同的属性,和微信的OpenData使用方式一模一样,实现组件的跨平台,传入的属性保持一致非常重要。