備注
這是很久以前保存的文件败玉,將原始的內(nèi)容放到這里以備不時(shí)之需赶掖。
目錄
1. 為什么要使用RN
1. 編程人員永遠(yuǎn)的夢(mèng)想
1. 一次編寫(xiě),到處運(yùn)行之路
1. C/Java/Qt
2. write once, run everywhere
2. learn once, write everywhere
1. Chrome撐起的夢(mèng)想
1. Electron/Chrome App
2. virtual-dom
1. 虛擬dom
3. React
1. Web
2. Native
2. 屏蔽了底層代碼, 學(xué)習(xí)成本低
1. 我的全棧工程師之路 => 21天精通React
3. 快速發(fā)版
4. 性能優(yōu)勢(shì)
5. 為什么不用Weex
1. 池建強(qiáng)的博客截圖
2. React Native Init
1. 初始框架的搭建
1. react-native init jumeiReactNative
2. 多項(xiàng)目的改造
1. 引入
3. React Native 工具包
1. Chrome Developer Tools
2. react-devtools
1. 安裝時(shí)需要在npmrc中指定electron地址: `ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/`
3. React Native工程化
1. 配置系統(tǒng)(接口開(kāi)關(guān))
1. 平臺(tái)控制
1. 項(xiàng)目開(kāi)關(guān)
1. 總開(kāi)關(guān)
1. 失敗次數(shù)控制
1. 系統(tǒng)版本控制(Android/iOS)
1. Rom版本控制(安卓定制系統(tǒng), iOS具體版型(iOS6/7/8))
1. 客戶端版本控制
1. CPU版本控制
當(dāng)檢測(cè)到可以開(kāi)啟RN后, 由客戶端下載bundle包
2. Module同步(bundle包下載)
1. 調(diào)用接口,獲取最新bundle列表
1. 依次檢測(cè)本地是否已下載過(guò)bundle包
檢測(cè)標(biāo)準(zhǔn):
1. 文件名相同
1. 版本號(hào)相同
1. 文件簽名相同
未下載 => 啟動(dòng)下載流程
1. bundle下載
1. 下載失敗
1. 網(wǎng)絡(luò)異常
1. 存儲(chǔ)空間不足
1. 解壓縮失敗
1. 校驗(yàn)不通過(guò)(文件hash不對(duì), 文件名不對(duì))
1. 下載成功
1. 校驗(yàn)并保存文件
已下載 => 跳過(guò)
3. 啟動(dòng)RN
1. 本地是否有對(duì)應(yīng)bundle
1. 存在 => 載入bundle
1. RN啟動(dòng)
1. 活動(dòng)流程是否正常(日常測(cè)試)
1. 原生通信是否正常, 是否可以正常調(diào)用原生功能(RN項(xiàng)目測(cè)試)
1. 檢查調(diào)用原生功能情況
1. 頁(yè)面跳轉(zhuǎn),返回,讀取本地存儲(chǔ),本地通知,Dialog,Toast彈出
2. 不存在 => 降級(jí)啟動(dòng)H5頁(yè)面
2. 日志記錄與上報(bào)
3. 測(cè)試過(guò)程中的Tips
4. 爬坑之路
2. 按路徑引入
3. setState
5. 資源推薦
1. [React Native標(biāo)準(zhǔn)文檔](http://reactnative.cn/docs/0.51/getting-started.html)
2. [React Native小書(shū)](https://hydrographer-vivian-23728.netlify.com/)
4. [React 樣式表手冊(cè)](https://shenbao.github.io/ishehui/html/RN%20%E5%9F%BA%E7%A1%80/React%20Native%20%E6%A0%B7%E5%BC%8F%E8%A1%A8%E6%8C%87%E5%8D%97.html#)
5. [React Native動(dòng)畫(huà)進(jìn)階(中文版)](https://future-challenger.gitbooks.io/react-native-animation/content/)
3. [構(gòu)建 F8 App / 官方React Native 開(kāi)發(fā)指南](https://f8-app.liaohuqiu.net/tutorials/)
6. [Redux 中文文檔(勸退指南)](http://cn.redux.js.org/)
6. 劣勢(shì)
1. 還處于快速發(fā)展期, 頻繁更新
2. 性能和原生頁(yè)面畢竟還是有差距, 不能繪制過(guò)于復(fù)雜的動(dòng)畫(huà)
正文
大家好, 今天由我和孫陽(yáng)來(lái)為大家做一下React Native的分享. 在這次的分享里, 我會(huì)先簡(jiǎn)單介紹一下React的相關(guān)知識(shí)和選用React Native的原因, 然后由孫陽(yáng)來(lái)為我們?cè)敿?xì)介紹下React Native具體的工程化過(guò)程, 最后會(huì)介紹一些項(xiàng)目實(shí)施中遇到的坑和相關(guān)的學(xué)習(xí)資源.
讓我們先從React開(kāi)始. React是Facebook編寫(xiě)的一套前端框架. 在React之前, 大家寫(xiě)HTML的思路是按標(biāo)簽去寫(xiě), p標(biāo)簽a標(biāo)簽之類(lèi)的, 然后如果想寫(xiě)一個(gè)復(fù)雜點(diǎn)的功能的話就需要把這些標(biāo)簽全都摞起來(lái), 一個(gè)個(gè)的調(diào)位置. 這種思路在標(biāo)簽量小的情況下還好, 但是標(biāo)簽量一大就會(huì)很難辦, 一大坨標(biāo)簽密密麻麻擠一堆, 誰(shuí)都維護(hù)不了. 當(dāng)然了, 在真實(shí)工作中碰到這種問(wèn)題我們也是有解決辦法的, 就是結(jié)構(gòu)化編程, 把標(biāo)簽按功能拆分開(kāi), 每個(gè)功能區(qū)之間互相獨(dú)立互不影響, 這樣一個(gè)頁(yè)面無(wú)論再怎么復(fù)雜, 都可以通過(guò)拆分的方式把它分成一個(gè)個(gè)的小塊, 我們只要組織好這些小塊就行了. 如果我們?cè)俳o這些小塊起一個(gè)專用的名字, 比如說(shuō)組件 => vue1.0 就誕生了. 但為什么這個(gè)思路只是vue1.0 不是React呢, 因?yàn)樵谖覀儎偛诺臉?gòu)想里, 組件和網(wǎng)頁(yè)元素標(biāo)簽還是一一對(duì)應(yīng)的, React比這更近一步, 他在組件和元素標(biāo)簽之間引入了一層虛擬dom, 組件被映射成虛擬的dom結(jié)構(gòu), 然后再由框架將這些虛擬的dom元素轉(zhuǎn)換成真正的HTML標(biāo)簽列表.
ok, 關(guān)鍵的地方來(lái)了. React的界面是由組件構(gòu)成的, 而我們知道安卓和iOS的界面也都是由和組件類(lèi)似的控件構(gòu)成的, 那么, 有沒(méi)有可能利用虛擬dom這個(gè)中間層, 把React的組件給轉(zhuǎn)換成安卓和iOS的組件呢?如果再加上底層庫(kù)的配合, 讓js可以請(qǐng)求網(wǎng)絡(luò)/存儲(chǔ)數(shù)據(jù)/觸發(fā)彈窗/記錄日志的話, 對(duì)于純數(shù)據(jù)的展示, 是不是就可以直接用React去寫(xiě)了呢? 當(dāng)然, 這些問(wèn)題我們現(xiàn)在都已經(jīng)知道答案了, 2015年4月, React Native第一版上線, React開(kāi)始支持iOS平臺(tái), 2015年9月, React Native正式支持Android的開(kāi)發(fā). 至此, 如果你會(huì)寫(xiě)React的話, 相當(dāng)于你不光能寫(xiě)網(wǎng)頁(yè), 同時(shí)也能寫(xiě)Android和iOS的應(yīng)用.
而且問(wèn)題在于, 跟iOS和Android開(kāi)發(fā)比起來(lái), React確實(shí)要更簡(jiǎn)單. 如果你是一個(gè)原生開(kāi)發(fā)人員, 系統(tǒng)自帶的數(shù)據(jù)庫(kù)存儲(chǔ)要會(huì), 文件系統(tǒng)結(jié)構(gòu)要會(huì), 進(jìn)程線程模型要知道, 事件模型要知道. 但是如果只是為了展示數(shù)據(jù)進(jìn)行交互的話, 根本不需要了解這些系統(tǒng)底層的知識(shí), 只要知道展示文本用Text組件, 展示圖片用Image組件就夠了. 而且, React發(fā)版速度也很快. 因?yàn)镽eact 項(xiàng)目就是一個(gè)js文本文件, 發(fā)版的時(shí)候只要把這個(gè)文本文件傳到網(wǎng)上, 更新下配置就可以.
總結(jié)一下: 對(duì)于展示頁(yè)面來(lái)說(shuō), React 技術(shù)棧 入門(mén)簡(jiǎn)單, 開(kāi)發(fā)效率高(一次編寫(xiě), 三端運(yùn)行), 發(fā)版速度快, 作為技術(shù)人員我們實(shí)際上沒(méi)什么理由不用React. 當(dāng)然, 有同學(xué)可能會(huì)問(wèn), Vue技術(shù)棧下邊也有和React Native相同的Weex, 為什么我們不直接沿用現(xiàn)在前端的技術(shù)棧, 而是要用一個(gè)全新的React技術(shù)棧呢. 這就是React 的另一項(xiàng)優(yōu)點(diǎn)了: 社區(qū)大,坑少.
React 2013年首次對(duì)外發(fā)布, 15年推出Native框架, 現(xiàn)在京東, QQ, 去哪兒都在大量使用React Native相關(guān)的技術(shù)棧, 可以說(shuō)是一套比較成熟的框架了. 但是基于Vue的Weex, 這個(gè), 也不多說(shuō)啥. 前段時(shí)間極客邦基于Weex推出了一款A(yù)pp, 這是他們?cè)诮Y(jié)項(xiàng)后的感謝辭: 感謝Weex團(tuán)隊(duì), 感謝張小龍幫忙協(xié)調(diào)資源, 然后在這么強(qiáng)的支持下, 極客時(shí)間項(xiàng)目整體延期, 10月17號(hào)iOS上線, 12月8號(hào)安卓才發(fā)布上線...然后, 如果我們的人脈沒(méi)有那么強(qiáng), 請(qǐng)不動(dòng)張小龍, 也找不到Weex開(kāi)發(fā)組, 然后這樣的話, 你們都懂.
介紹完React Native, 我們來(lái)講下它的具體使用.
首先當(dāng)然是執(zhí)行react-native init jumeiReactNative
初始化項(xiàng)目, 然后npm install
安裝依賴, react-native run-android
啟動(dòng)debug模式. 這些官網(wǎng)上都有, 我這兒就不多說(shuō)了.
重點(diǎn)要介紹的是這兩個(gè)地方:
- 首先, 我們來(lái)看下RN的代碼, 他這個(gè)就是React的代碼, 沒(méi)有其他多余的東西. 也就是說(shuō), React Native確實(shí)像他描述的一樣, 只要會(huì)寫(xiě)React 就能寫(xiě)React Native. 沒(méi)有其他學(xué)習(xí)成本
- 因?yàn)镽eact Native的代碼只是一層皮, 他的本質(zhì)是被編譯好了的, 隨時(shí)可以修改的js, 因此React Native的代碼可以和普通的js代碼一樣調(diào)試, 而且還可以直接在Chrome瀏覽器里打日志, 單步調(diào)試. 就像這樣(開(kāi)啟遠(yuǎn)程調(diào)試功能, 展示Chrome瀏覽器下的日志打印和單步調(diào)試功能)
- 除了這些, 我們還可以直接用react-devtools查看組件的效果(展示react-devtools的效果). 不過(guò)這里有個(gè)小坑, 因?yàn)檫@個(gè)工具用到了electron, 而electron的安裝地址又被國(guó)家屏蔽了, 所以安裝工具的時(shí)候經(jīng)常會(huì)因?yàn)榫W(wǎng)絡(luò)異常失敗. 所以我們需要在系統(tǒng)的npmrc配置里指定electron的安裝源才行.
- 然后順帶講一下, 他這里的electron實(shí)際上跟我們的RN是一樣的, 也是提供一個(gè)殼, 然后里邊實(shí)際跑的是js代碼. 比如現(xiàn)在前端開(kāi)發(fā)常用的VS Code 編輯器, 實(shí)際上就是用Chrome瀏覽器加上HTML畫(huà)出來(lái)的. 15年之后各種桌面系統(tǒng)的原生開(kāi)發(fā)在事實(shí)上已經(jīng)停滯了, 現(xiàn)在新出的軟件都是用js+chrome瀏覽器外殼去實(shí)現(xiàn). React Native其實(shí)只是這種浪潮下的一個(gè)分支而已.
然后, 關(guān)于RN的基礎(chǔ)知識(shí)已經(jīng)講的差不多了, 下面讓我們請(qǐng)孫陽(yáng)來(lái)為我們介紹下聚美RN的具體實(shí)施過(guò)程.
孫陽(yáng)部分
ok, 孫陽(yáng)分享完了測(cè)試的要點(diǎn), 我來(lái)分享下RN項(xiàng)目在開(kāi)發(fā)時(shí)的一些坑.
先是一個(gè)小坑:
- 按路徑引入
- react-native里有一個(gè)小問(wèn)題, 就是它默認(rèn)只能用相對(duì)路徑去引入模塊. 這樣就意味著我們?cè)趯?xiě)代碼的時(shí)候要寫(xiě)一大堆的"../.."去回到根目錄, 而且代碼目錄越深".."就用的越多, 寫(xiě)起來(lái)非常惡心.
- 不過(guò)RN提供了一個(gè)hack的方式, 就是我們可以通過(guò)在指定目錄下添加一個(gè)package.json的文件來(lái)給一個(gè)目錄指定模塊名, 比如, 我們可以在src目錄下添加一個(gè)package.json, 內(nèi)容是
{ "name": "src" }
, 這樣src這個(gè)目錄就會(huì)被RN識(shí)別為src模塊, 以后引用的時(shí)候就可以直接引了 - 之所以說(shuō)這是一個(gè)坑是因?yàn)檫@個(gè)解決方案在中文網(wǎng)絡(luò)里沒(méi)有, 是在Github的一個(gè)issue里找到的, 所以專門(mén)提一下
然后有一個(gè)狀態(tài)管理的大坑.
RN的樣式展示和邏輯代碼是分屬與兩個(gè)線程的. 當(dāng)邏輯線程更新了組件狀態(tài), 樣式展示代碼就會(huì)根據(jù)新?tīng)顟B(tài)去渲染組件. 這個(gè)看起來(lái)沒(méi)什么問(wèn)題, 但是在實(shí)踐的時(shí)候出現(xiàn)了這種情況, 就是: 邏輯線程在更新完?duì)顟B(tài)之后自動(dòng)退出, 然后RN所在的Activity也跟著被回收了回去, 這里沒(méi)問(wèn)題, 但是因?yàn)榫€程之間的消息不同步, 然后輪到樣式展示線程的時(shí)候展示線程看到狀態(tài)有更新, 就直接去更新組件, 但是組件又不存在, 導(dǎo)致代碼Crash.
這其實(shí)很坑,因?yàn)闄z測(cè)組件存不存在這種事屬于臟活,而且也是基礎(chǔ)功能, 應(yīng)該由框架自己負(fù)責(zé).我當(dāng)時(shí)沒(méi)想到RN發(fā)展了兩年連這個(gè)功能都沒(méi)做,所以也沒(méi)忘這塊考慮, 導(dǎo)致這一個(gè)bug找了半天. 不過(guò)這個(gè)bug最后是這么解決的: 我們加了一個(gè)onMounted信號(hào)量, 組件載入就設(shè)成true, 組件銷(xiāo)毀就改成false, 然后在每次更新?tīng)顟B(tài)和更新組件前都檢測(cè)一下這個(gè)信號(hào)量, 如果為false就直接返回.這樣才算是解決了.
最后一點(diǎn)就是性能問(wèn)題. 前面說(shuō)了, RN雖然最后會(huì)被翻譯成原生代碼進(jìn)行執(zhí)行, 但是畢竟經(jīng)過(guò)了一層虛擬dom中間層, 導(dǎo)致他的性能肯定會(huì)比真正的原生要差一點(diǎn).因此RN不適合展示復(fù)雜的動(dòng)畫(huà), 這點(diǎn)需要注意.
好了, 最后再介紹一下RN的學(xué)習(xí)資源
首先是官方文檔, 這個(gè)不用說(shuō)了, 從搭建環(huán)境到實(shí)際開(kāi)發(fā), 肯定要經(jīng)常翻看的.
然后是React Native小書(shū), 這是一本由中國(guó)開(kāi)發(fā)者寫(xiě)的RN介紹, 建議搭建完環(huán)境后就直接看這本書(shū), 在引領(lǐng)入門(mén)方面寫(xiě)的比文檔要好.
然后是RN支持的全部樣式表和RN的動(dòng)畫(huà)手冊(cè), 這塊前端同學(xué)在開(kāi)發(fā)的時(shí)候肯定要翻的.
最后是一個(gè)Facebook官方的示例代碼, 和Redux使用指南. 官方示例這個(gè)就不說(shuō)了, 直接看就行. Redux這個(gè)要說(shuō)一下. 一般來(lái)說(shuō)大型React系統(tǒng)都需要上Redux去管理組件的各種狀態(tài), 但是如果是小項(xiàng)目的話, 文檔和我的建議都是不要上這個(gè), 對(duì)于我們平常用的小頁(yè)面來(lái)說(shuō), 它帶來(lái)的復(fù)雜度的提升會(huì)遠(yuǎn)遠(yuǎn)大于引入他所能獲得的在開(kāi)發(fā)效率上的收益.
我們的分享講完了, 謝謝大家