Taro跨平臺開發(fā)實踐

文章發(fā)表于 http://blog.poetries.top/2019/06/08/taro-summary

一氓侧、小程序開發(fā)框架

image.png

Vue-like、React-like 代碼,如何在小程序中運行?

image.png

1.1 基本原理

  • 編譯時處理(轉(zhuǎn)譯成小程序語法)
  • 運行時適配(管理生命周期、數(shù)據(jù),處理事件等)

編譯原理

源代碼->詞法/語法/語義分析->抽象語法樹->轉(zhuǎn)換->目標代碼

image.png

抽象語法樹 AST

image.png

1.2 小程序框架多端支持情況

image.png

二突颊、Taro原理

Taro: 多端統(tǒng)一開發(fā)框架,支持用 React 的開發(fā)方式編寫一次代
碼潘悼,生成能運行在微信小程序律秃、H5、React Native 等的應用

image.png
image.png
image.png
image.png

多端能力:提供對應端的runtime治唤、組件棒动、redux、router等實現(xiàn)

image.png
image.png
image.png
image.png
  • 提供相應端的 Runtime 實現(xiàn)肝劲,具備適配 API 的能力
  • 提供統(tǒng)一的基礎(chǔ)組件迁客,編譯時替換為相應端的組件實現(xiàn)

三、Taro項目中遇到的坑

3.1 一些坑

1辞槐、React-like掷漱,不完全等同 React

image.png

2、端能力差異不可避免:某些功能在相應端上沒有支持

image.png

3榄檬、樣式支持卜范、寫法上存在差異

image.png
image.png
image.png

4、還沒有真正支持多端的 UI 組件庫能在 Taro 上使用

image.png

5鹿榜、React Native 的 view 不支持 click 事件海雪,需要用 Touchable 組件

image.png

6、React Native 不支持 text-overflow舱殿,而是提供原生支持(Text 組件傳入 numberOfLines={num} 屬性)

Taro 目前沒有暴露原生 RN Text 組件的 numberOfLines 屬性奥裸。因此目前通過 Text 基礎(chǔ)組件沒法實現(xiàn)多端統(tǒng)一的文本截斷

H5情況較為樂觀

  • 主要差異1: 小程序的頁面、組件樣式都是獨立的沪袭,H5會受同名樣式影響
  • 主要差異2: 小程序的組件多了一層標簽
image.png

7湾宙、多端要求較高

  • 對不同端的具體差異有所了解
  • 樣式實現(xiàn)較為苛刻,需兼顧多端冈绊、有所取舍
  • 端能力差異可能需要自己填坑

8侠鳄、多端填坑方式

image.png

多端實踐經(jīng)驗

  • 對多端差異做好封裝
  • 采用 BEM 命名方式管理樣式
  • 采用全局樣式維護基礎(chǔ)組件 @taro/components 的樣式
  • 基于 @taro/components 自行封裝組件庫

3.2 注意事項

  • 函數(shù)需要on+函數(shù)名來規(guī)范命名
  • 子組件中接收的props需要定義defaultProps。否則小程序端報錯
  • Taro 中死宣,JS 代碼里必須書寫單引號伟恶,特別是 JSX 中,如果出現(xiàn)雙引號毅该,可能會導致編譯錯誤
  • css樣式單位寫PX大寫會轉(zhuǎn)成rem單位
  • 根據(jù)環(huán)境變量引入不同平臺組件博秫、編譯到對應平臺
  • 小程序端不支持在render()之外定義jsx潦牛。比如在外面renderForm()
  • 頁面布局:拆分組件方法--由上到下,由左到右拆分
  • Taro 目前還沒有支持 React.Fragment 語法
  • 運行時 報缺少包挡育,需要要在 .rn_temp 目錄里面安裝
  • 文字要包在 Text 組件里面罢绽,否則不顯示
  • position:fixed React Native 不支持
  • Animationtransform React Native 動畫不支持
  • 狀態(tài)更新一定是異步的。React的狀態(tài)更新不一定是異步

四静盅、技巧

4.1 樣式文件條件編譯

假設(shè)目錄中同時存在以下文件:

- index.scss
- index.rn.scss

當在 JS文件中引用樣式文件:import './index.scss' 時,RN 平臺會找到并引入 index.rn.scss寝殴,其他平臺會引入:index.scss蒿叠,方便大家書寫跨端樣式,更好地兼容 RN

4.2 內(nèi)置環(huán)境變量

process.env.TARO_ENV

用于判斷當前編譯類型蚣常,目前有 weapp / swan / alipay / h5 / rn / tt六個取值市咽,可以通過這個變量來書寫對應一些不同環(huán)境下的代碼,在編譯時會將不屬于當前編譯類型的代碼去掉抵蚊,只保留當前編譯類型下的代碼施绎,例如想在微信小程序和 H5 端分別引用不同資源

if (process.env.TARO_ENV === 'weapp') {
  require('path/to/weapp/name')
} else if (process.env.TARO_ENV === 'h5') {
  require('path/to/h5/name')
}

同時也可以在 JSX 中使用,決定不同端要加載的組件

render () {
  return (
    <View>
      {process.env.TARO_ENV === 'weapp' && <ScrollViewWeapp />}
      {process.env.TARO_ENV === 'h5' && <ScrollViewH5 />}
    </View>
  )
}

4.3 統(tǒng)一接口的多端文件

多端組件

  • 假如有一個 Test 組件存在微信小程序贞绳、百度小程序和 H5 三個不同版本谷醉,那么就可以像如下組織代碼
  • test.js 文件,這是 Test 組件默認的形式冈闭,編譯到微信小程序俱尼、百度小程序和 H5 三端之外的端使用的版本
  • test.h5.js 文件,這是 Test 組件的 H5 版本
  • test.weapp.js 文件萎攒,這是 Test組件的 微信小程序 版本
  • test.swan.js 文件遇八,這是 Test 組件的 百度小程序 版本
  • 四個文件,對外暴露的是統(tǒng)一的接口耍休,它們接受一致的參數(shù)刃永,只是內(nèi)部有針對各自平臺的代碼實現(xiàn)
  • 而我們使用 Test 組件的時候,引用的方式依然和之前保持一致羊精,import 的是不帶端類型的文件名斯够,在編譯的時候會自動識別并添加端類型后綴
import Test from '../../components/test'

<Test argA={1} argA={2} />

多端腳本邏輯

例如微信小程序上使用 Taro.setNavigationBarTitle 來設(shè)置頁面標題,H5 使用 document.title园匹,那么可以封裝一個 setTitle 方法來抹平兩個平臺的差異

增加 set_title.h5.js雳刺,代碼如下

export default function setTitle (title) {
  document.title = title
}

增加 set_title.weapp.js,代碼如下

import Taro from '@tarojs/taro'
export default function setTitle (title) {
  Taro.setNavigationBarTitle({
    title
  })
}

調(diào)用的時候裸违,如下使用

import setTitle from '../utils/set_title'

setTitle('頁面標題')

五掖桦、React Native端的實踐

https://nervjs.github.io/taro/docs/react-native.html

5.1 Taro運行RN步驟

1. 運行 yarn dev:rn

image.png

打開 http://127.0.0.1:8081/index.bundle?platform=ios&dev=true激活編譯

image.png

2. 下載react-native運行殼子

https://github.com/poetries/react-native-shell

3. 打開gemotion安卓模擬器

  • 參考文章
  • adb devices 查看是否有設(shè)備在運行

4. 啟動安卓

在殼子中啟動命令。react-native-shell 放在哪里都可以供汛,建議放到項目根目錄即可

react-native run-android

5. 打包apk

react-native-shell中的android文件加拷貝到.rn_temp文件中枪汪,cd android 執(zhí)行打包命令即可

參考文章

5.2 樣式

Note:如果要支持 React Native 端涌穆,必須采用 Flex 布局,并且樣式選擇器僅支持類選擇器雀久,且不 支持 組合器

以下選擇器的寫法都是不支持的宿稀,在樣式轉(zhuǎn)換時會自動忽略

.button.button_theme_islands{
  font-style: bold;
}

img + p {
  font-style: bold;
}

p ~ span {
  color: red;
}

div > span {
  background-color: DodgerBlue;
}

div span { background-color: DodgerBlue; }

樣式上 H5 最為靈活,小程序次之赖捌,RN 最弱祝沸,統(tǒng)一多端樣式即是對齊短板,也就是要以 RN 的約束來管理樣式越庇,同時兼顧小程序的限制罩锐,核心可以用三點來概括

  • 使用 Flex 布局
  • 基于 BEM 寫樣式
  • 采用 style 屬性覆蓋組件樣式

RNView 標簽默認主軸方向是 column,如果不將其他端改成與 RN 一致卤唉,就需要在所有用到 display: flex 的地方都顯式聲明主軸方向

5.3 問題

盡量避免在 componentDidMount 中調(diào)用 this.setState

因為在 componentDidMount 中調(diào)用 this.setState 會導致觸發(fā)更新

import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'

class MyComponent extends Component {
  state = {
    myTime: 12
  }
  
  componentDidMount () {
    this.setState({     // ? 盡量避免涩惑,可以在 componentWillMount 中處理
      name: 1
    })
  }
  
  render () {
    const { isEnable } = this.props
    const { myTime } = this.state
    return (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}

不要定義沒有用到的 state

import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'

class MyComponent extends Component {
  state = {
    myTime: 12,
    noUsed: true   // ? 沒有用到
  }
  
  render () {
    const { myTime } = this.state
    return (
      <View className='test'>
        <Text className='test_text'>{myTime}</Text>
      </View>
    )
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市桑驱,隨后出現(xiàn)的幾起案子竭恬,更是在濱河造成了極大的恐慌,老刑警劉巖熬的,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痊硕,死亡現(xiàn)場離奇詭異,居然都是意外死亡押框,警方通過查閱死者的電腦和手機寿桨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强戴,“玉大人亭螟,你說我怎么就攤上這事∑锎酰” “怎么了预烙?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長道媚。 經(jīng)常有香客問我扁掸,道長,這世上最難降的妖魔是什么最域? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任谴分,我火速辦了婚禮,結(jié)果婚禮上镀脂,老公的妹妹穿的比我還像新娘牺蹄。我一直安慰自己,他們只是感情好薄翅,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布沙兰。 她就那樣靜靜地躺著氓奈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鼎天。 梳的紋絲不亂的頭發(fā)上舀奶,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音斋射,去河邊找鬼育勺。 笑死,一個胖子當著我的面吹牛罗岖,可吹牛的內(nèi)容都是我干的怀大。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼呀闻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潜慎?” 一聲冷哼從身側(cè)響起捡多,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铐炫,沒想到半個月后垒手,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡倒信,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年科贬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳖悠。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡榜掌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乘综,到底是詐尸還是另有隱情憎账,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布卡辰,位于F島的核電站胞皱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏九妈。R本人自食惡果不足惜反砌,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萌朱。 院中可真熱鬧宴树,春花似錦、人聲如沸晶疼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至同衣,卻和暖如春竟块,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耐齐。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工浪秘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人埠况。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓耸携,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辕翰。 傳聞我的和親對象是個殘疾皇子夺衍,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容