1.What is React Native

眾所周知,產(chǎn)品的需求總是想快速的迭代。但是由于應(yīng)用分發(fā)市場的審核機(jī)制(主要是iOS審核),使一些快速迭代的需求只能選擇web作為應(yīng)用場景。雖然web應(yīng)用已經(jīng)是一個(gè)很成熟的業(yè)務(wù),H5的助力也使web應(yīng)用快速占據(jù)移動(dòng)市場。但是web應(yīng)用有web應(yīng)用的瓶頸,在一些交互、性能方面還是無法媲美原生應(yīng)用。這個(gè)時(shí)候,React Native的出現(xiàn),也許給我們帶來了一點(diǎn)點(diǎn)新的思路。React Native從出生就帶有著,跨平臺,快速迭代,節(jié)省安裝包等標(biāo)簽。在React Native之前,也有很多技術(shù)意圖跨平臺,但是真正做到完全跨平臺的技術(shù),準(zhǔn)確來說應(yīng)該是沒有的。也許React Native提出的‘Learn once, write anywhere’可行。本次,就以一個(gè)小白的視角,來管中窺豹一下React Native。
2.工欲善其事,必現(xiàn)利其器

工欲善其事,必現(xiàn)利其器是自古以來不變的道理。在我們平時(shí)開發(fā)的時(shí)候,一款好的IDE會(huì)使我們的開發(fā)效率成倍提升。而好的IDE也會(huì)助力于好的語言的未來發(fā)展。就像oc或者swift,就伴隨著xcode;c++或者c#,大家肯定想到visual stutio。

雖然說,開發(fā)React Native的IDE有很多。著名的有Nuclide,Sublime,WebStrom。但是,個(gè)人比較偏愛于WebStrom,這款號稱最聰明的javascript IDE。
3.JSX
//使用JSX
React.render(
<div>
<div>
<div>demo</div>
</div>
</div>,
document.getElementById('demo')
);
//不使用JSX
React.render(
React.createElement('div', null,
React.createElement('div', null,
React.createElement('div', null, 'demo')
)
),
document.getElementById('demo')
);
JSX語法,像是在Javascript代碼里直接寫XML的語法,實(shí)質(zhì)上這只是一個(gè)語法糖,每一個(gè)XML標(biāo)簽都會(huì)被JSX轉(zhuǎn)換工具轉(zhuǎn)換成純Javascript代碼,React 官方推薦使用JSX, 當(dāng)然你想直接使用純Javascript代碼寫也是可以的,只是使用JSX,組件的結(jié)構(gòu)和組件之間的關(guān)系看上去更加清晰。
4.ES6
我們在看React Native的同時(shí),首先得了解React Native使用的語言。ES6作為javascript語言下一代標(biāo)準(zhǔn),我們稍微了解一下幾個(gè)關(guān)鍵的ES6的語法,會(huì)更好的理解React Native。
let,const
let和var一樣都可以聲明變量。只是不同都是,let為javascript新增了作用域的概念,用他聲明的變量,只在命令所在的代碼塊內(nèi)有效。
const也可以用了聲明變量,但是聲明的是常量。一旦聲明,就不能改變其中的值。
class,extends,super
class Dog{
constructor(){
this.type = 'Dog';
}
eat(){
console.log(this.type + " eat");
}
}
let Dog = new Dog();
Dog.eat();//Dog eat
class BigDog extends Dog{
constructor(){
super();
this.type = 'BigDog';
}
}
let BigDog = new BigDog();
BigDog.eat();//BigDog eat
arrow function
更簡潔的函數(shù)書寫
function(x, y) {
x++;
y‐‐;
return x + y;
} //舊寫法
(x, y) => {x++; y‐‐; return x+y} //新寫法
default,rest
default很簡單,意思就是默認(rèn)值。大家可以看下面的例子,調(diào)用 say() 方法時(shí)忘了傳參
數(shù),傳統(tǒng)的做法就是加上這一句 type = type || '1' 來指定默認(rèn)值。
如果用ES6我們而已直接這么寫:
function say(type = '1'){
console.log(type)
}
say()//''1''
最后一個(gè)rest語法也很簡單,直接看例子:
function say(...types){
console.log(types)
}
say('1', '2, '3') //["1", "2", "3"]
import export
有了這兩個(gè)關(guān)鍵字。我們就可以像iOS一樣,把不同的js當(dāng)成不同的模塊,需要暴漏出來的export出來。需要引用的import進(jìn)來。
5.布局
像素密度
React Native 提供的是像素?zé)o關(guān)的長度單位
Flex in React Native
Flex布局類似于web中的Flex布局,只不過,在React Native中的Flex布局取了web中的Flex布局的子集。
絕對布局和相對布局
React Native中的絕對布局和相對布局,就有點(diǎn)像我們傳統(tǒng)終端開發(fā)中的布局方式,區(qū)別是一個(gè)是相對路徑,一個(gè)是絕對路徑。
6.pros&state

state
state是React中組件的一個(gè)對象.React把用戶界面當(dāng)做是狀態(tài)機(jī),想象它有不同的狀態(tài)然后渲染這些狀態(tài),可以輕松讓用戶界面與數(shù)據(jù)保持一致.
React中,更新組件的state,會(huì)導(dǎo)致重新渲染用戶界面(不要操作DOM).簡單來說,就是用戶界面會(huì)隨著state變化而變化.
props
組件中的props是一種父級向子級傳遞數(shù)據(jù)的方式.
7.Virtual Dom

DOM操作很慢是兩個(gè)原因,一個(gè)是因?yàn)樾枰僮骶唧w的native控件,這本身操作就不快,第二是我們處理dom的方式很慢,Virtual Dom解決了我們對Dom的低劣操作,它的想法是,它想讓我們不需要直接進(jìn)行Dom操作,而是將希望展現(xiàn)的最終結(jié)果告訴React,React通過js構(gòu)造一個(gè)新的數(shù)據(jù)結(jié)構(gòu)即Virtual dom進(jìn)行render,這個(gè)Virtual dom 僅僅存在于數(shù)據(jù)結(jié)構(gòu)中,并沒有實(shí)際渲染出Dom。當(dāng)你試圖改變顯示內(nèi)容時(shí),新生成的Virtual Dom會(huì)與現(xiàn)在的Virtual dom對比,通過diff算法找到區(qū)別,這些操作都是在快速的js中完成的,最后對實(shí)際Dom進(jìn)行最小的Dom操作來完成效果,這就是Virtual Dom的概念??偨Y(jié)的來說,就是通過引入新的數(shù)據(jù)結(jié)構(gòu),計(jì)算出最小移動(dòng)Dom的方法,再去真實(shí)操作Dom,這樣的成本是最低的。
8.DIFF算法
傳統(tǒng) diff 算法
計(jì)算一棵樹形結(jié)構(gòu)轉(zhuǎn)換成另一棵樹形結(jié)構(gòu)的最少操作,這是一個(gè)復(fù)雜且值得研究的問題。傳統(tǒng) diff 算法通過循環(huán)遞歸對節(jié)點(diǎn)進(jìn)行依次對比,效率低下,算法復(fù)雜度達(dá)到 O(n3),其中 n 是樹中節(jié)點(diǎn)的總數(shù)。
React diff
傳統(tǒng) diff 算法的復(fù)雜度為 O(n3),顯然這是無法滿足性能要求的。React 通過制定大膽的策略,將 O(n3) 復(fù)雜度的問題轉(zhuǎn)換成 O(n) 復(fù)雜度的問題。
1.UI 中 DOM 節(jié)點(diǎn)跨層級的移動(dòng)操作特別少,可以忽略不計(jì)。
2擁有相同類的兩個(gè)組件將會(huì)生成相似的樹形結(jié)構(gòu),擁有不同類的兩個(gè)組件將會(huì)生成不同的樹形結(jié)構(gòu)。
3.對于同一層級的一組子節(jié)點(diǎn),它們可以通過唯一 id 進(jìn)行區(qū)分。
基于以上三個(gè)前提策略,React 分別對 tree diff、component diff 以及 element diff 進(jìn)行算法優(yōu)化,事實(shí)也證明這三個(gè)前提策略是合理且準(zhǔn)確的,它保證了整體界面構(gòu)建的性能。而這種算法的優(yōu)化,也使算法復(fù)雜度,趨緊于O(n) 。大大提升了性能。
9.React Native生命周期

React Native的生命周期和我們終端開發(fā)中所接觸的生命周期不太一樣。React Native的構(gòu)成是組件化,所以,生命周期也就圍繞著組建的創(chuàng)建,組建的更新,組建的消亡展開的。
組件生命周期大致分為三個(gè)階段:
第一階段:組建的創(chuàng)建,這是組件第一次繪制階段,這里會(huì)進(jìn)入組建的初始化函數(shù)。
第二階段:在是組件在運(yùn)行和交互階段,這個(gè)階段組件可以處理用戶交互,或者接收事件更新界面;
第三階段:是組件卸載消亡的階段,組建會(huì)做一些銷毀函數(shù)。
10.React Native自定義控件

React Native對插件的支持非常解耦合。比如,我們想添加一個(gè)Video的插件,我們就可以 直接輸入 npm install react-native-video --save,然后再輸入 react-native link,就自動(dòng)向native模塊中添加了各種依賴和導(dǎo)包的操作。

以上工程目錄就可以看到,video插件已經(jīng)link到工程目錄中了。
11.React Native Debug
紅屏

紅屏錯(cuò)誤只有在debug模式中才會(huì)出現(xiàn)。在React Native中一旦出現(xiàn)了紅屏問題,就說明你的js代碼在運(yùn)行中出了錯(cuò)誤,一般的錯(cuò)誤紅屏?xí)苯又赋龀鲥e(cuò)的行數(shù)或者錯(cuò)誤的類型以及堆棧信息。如果沒有指出的話,那就得依靠調(diào)試工具或者log信息了。
Chrome Debug

React Native的調(diào)試神器就是Chrome,安裝Chrome插件。模擬器選擇command + R 真機(jī)選擇搖一搖,就可以喚出Debug Menu。選擇debug in chrome,就可以喚出chrome調(diào)試器。chrome調(diào)試器非常強(qiáng)大,像普通的單步斷點(diǎn)調(diào)試,條件調(diào)試,堆棧信息等。
Log

Log的信息無論是開發(fā)環(huán)境還是生產(chǎn)環(huán)境都是很重要的。chrome debug可以直接在命令行中打印出log信息。生產(chǎn)環(huán)境,可以選擇將log打印到文件中,進(jìn)行上報(bào)分析。
12.Hot Reload

所見即所得是React Native的一大亮點(diǎn)。無論是真機(jī)還是模擬器,只要填好對應(yīng)的ip。就可以實(shí)時(shí)顯示代碼。模擬器選擇command + R 真機(jī)選擇搖一搖,就可以喚出Debug Menu??梢栽贒ebug Menu中選擇Hot Reload 的方式。
13.小結(jié)
本次帶著大家,走馬觀花式的觀看了React Native的簡介,語言以及重要語法,樣式,性能分析,重要的state&props ,生命周期等等。這些介紹雖然淺淺介紹,沒有深入探究。但是這樣的管中窺豹,希望大家對React Native有了一點(diǎn)點(diǎn)大概的印象,起到小白入門的作用。