1.RN簡(jiǎn)介
React Native
(簡(jiǎn)稱RN)是Facebook于2015年4月開源的跨平臺(tái)移動(dòng)應(yīng)用開發(fā)框架从绘,是Facebook早先開源的JS框架React
在原生移動(dòng)應(yīng)用平臺(tái)的衍生產(chǎn)物,目前支持iOS和安卓?jī)纱笃脚_(tái)芳杏。RN使用Javascript
語言肆汹,類似于HTML
的JSX
,以及CSS
來開發(fā)移動(dòng)應(yīng)用,因此熟悉Web前端開發(fā)的技術(shù)人員只需很少的學(xué)習(xí)就可以進(jìn)入移動(dòng)應(yīng)用開發(fā)領(lǐng)域音念。
React Native
看起來很像 React
,只不過其基礎(chǔ)組件是原生組件而非 web 組件躏敢。要理解 React Native
應(yīng)用的基本結(jié)構(gòu)症昏,首先需要了解一些基本的 React
的概念,比如 JSX
語法父丰、組件肝谭、state
狀態(tài)以及props
屬性。
React Native開發(fā)特點(diǎn):
- 一次學(xué)習(xí)蛾扇,隨處編寫:使用React Native可以為iOS和Android操作系統(tǒng)開發(fā)應(yīng)用程序攘烛,不同平臺(tái)上的代碼根據(jù)平臺(tái)會(huì)有一些微小的區(qū)別。
- 混合開發(fā):React Native代碼開發(fā)的模塊與原生代碼開發(fā)的模塊可以雙向通信镀首、無縫銜接坟漱;
- 高效的移動(dòng)應(yīng)用開發(fā):
(1)獨(dú)特的UI實(shí)現(xiàn)框架
(2)組件化開發(fā)
(3)跨平臺(tái)移植代碼迅速
(4)自動(dòng)匹配不同屏幕大小的手機(jī)
- 高效的移動(dòng)應(yīng)用開發(fā)調(diào)試
- 高效的應(yīng)用熱更新
- 有效降低移動(dòng)應(yīng)用安裝包體積
- 學(xué)習(xí)門檻低、開發(fā)難度低
使用React Native開發(fā)的代價(jià)
為了得到React Native開發(fā)的優(yōu)點(diǎn)更哄,使用React Native開發(fā)的APP也需要付出一定的代價(jià)芋齿。
- (1)內(nèi)存消耗大
使用React Native開發(fā)的程序運(yùn)行所需的內(nèi)存比原生代碼開發(fā)的程序略多腥寇。 - (2)運(yùn)行速度
使用React Native開發(fā)的代碼運(yùn)行速度比原生代碼略慢。
React 與 React Native 除了在編碼表現(xiàn)層都使用 JSX 語法外觅捆,在 React 與 React Native 的底層都有 Virtual DOM 與 DOM 之間的映射與轉(zhuǎn)換赦役,以實(shí)現(xiàn)了頁(yè)面組件高效更新的前端表現(xiàn)。
現(xiàn)在最新版本是0.59React Native中文網(wǎng)
React Native
與React
的關(guān)系及特點(diǎn):React
是基礎(chǔ)框架栅炒,是一套基礎(chǔ)設(shè)計(jì)實(shí)現(xiàn)理念掂摔,開發(fā)者不能直接使用它來開發(fā)移動(dòng)應(yīng)用或網(wǎng)頁(yè)。在React
之上發(fā)展出了React.js
框架用來開發(fā)網(wǎng)頁(yè)赢赊,發(fā)展出來React Native
用來開發(fā)移動(dòng)應(yīng)用乙漓。底層原理是相同的,都是使用js實(shí)現(xiàn)虛擬dom樹來驅(qū)動(dòng)頁(yè)面的渲染释移,react是驅(qū)動(dòng)HTML dom的渲染叭披,react native是驅(qū)動(dòng)原生組件的渲染。
React.js
:目的 是為了使前端的V層更具組件化玩讳,能更好的復(fù)用涩蜘,它能夠使用簡(jiǎn)單的html標(biāo)簽創(chuàng)建更多的自定義組件標(biāo)簽,內(nèi)部綁定事件锋边,同時(shí)可以讓你從操作dom中解脫出來皱坛,只需要操作數(shù)據(jù)就會(huì)改變相應(yīng)的dom。
二者都是基于組件(component
)開發(fā)豆巨,然后組件和組件之間通過props
傳遞方法剩辟,每個(gè)組件都有一個(gè)狀態(tài)(state)
,當(dāng)某個(gè)方法改變了這個(gè)狀態(tài)值時(shí)往扔,整個(gè)組件就會(huì)重繪贩猎,從而達(dá)到刷新。另外萍膛,說到重繪就要提到虛擬dom
了吭服,就是用js模擬dom
結(jié)構(gòu),等整個(gè)組件的dom
更新完畢蝗罗,它會(huì)有一個(gè)diff
的過程艇棕,對(duì)比出哪些組件發(fā)生了變化,然后才渲染到頁(yè)面串塑,簡(jiǎn)單來說只更新了相比之前改變了的部分沼琉,而不是全部刷新,所以效率很高桩匪。
虛擬DOM(Virtual DOM)
的機(jī)制:在瀏覽器端用Javascript
實(shí)現(xiàn)了一套DOM API
打瘪。基于React
進(jìn)行開發(fā)時(shí)所有的DOM
構(gòu)造都是通過虛擬DOM
進(jìn)行,每當(dāng)數(shù)據(jù)變化時(shí)闺骚,React都會(huì)重新構(gòu)建整個(gè)DOM樹彩扔,然后React將當(dāng)前整個(gè)DOM樹和上一次的DOM樹進(jìn)行對(duì)比,得到DOM結(jié)構(gòu)的區(qū)別僻爽,然后僅僅將需要變化的部分進(jìn)行實(shí)際的瀏覽器DOM更新虫碉。而且React能夠批處理虛擬DOM的刷新,在一個(gè)事件循環(huán)(Event Loop)內(nèi)的兩次數(shù)據(jù)變化會(huì)被合并进泼。
2.React詳解
生態(tài)介紹
Vue生態(tài):Vue + Vue-Router + Vuex + Axios + Babel + Webpack
React生態(tài):React + React-Router + Redux + Axios + Babel + Webpack
2.1.React 簡(jiǎn)介
React
是一個(gè)聲明式蔗衡,高效且靈活的用于構(gòu)建用戶界面的 JavaScript 庫(kù)纤虽。使用 React 可以將一些簡(jiǎn)短乳绕、獨(dú)立的代碼片段組合成復(fù)雜的 UI 界面,這些代碼片段被稱作“組件”逼纸。
React
特點(diǎn)
- 1.聲明式設(shè)計(jì) ?
React
采用聲明范式洋措,可以輕松描述應(yīng)用。 - 2.高效 ?
React
通過對(duì)DOM的模擬杰刽,最大限度地減少與DOM的交互菠发。 - 3.靈活 ?
React
可以與已知的庫(kù)或框架很好地配合。 - 4.JSX ?
JSX
是JavaScript
語法的擴(kuò)展贺嫂。React 開發(fā)不一定使用 JSX 滓鸠,但我們建議使用它。 - 5.組件 ? 通過
React
構(gòu)建組件第喳,使得代碼更加容易得到復(fù)用糜俗,能夠很好的應(yīng)用在大項(xiàng)目的開發(fā)中。 - 6.單向響應(yīng)的數(shù)據(jù)流 ?
React
實(shí)現(xiàn)了單向響應(yīng)的數(shù)據(jù)流曲饱,從而減少了重復(fù)代碼悠抹,這也是它為什么比傳統(tǒng)數(shù)據(jù)綁定更簡(jiǎn)單。
2.2 React使用
1.React 環(huán)境配置安裝
- 使用 React CDN 庫(kù)
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生產(chǎn)環(huán)境中不建議使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 官方提供的CDN-->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生產(chǎn)環(huán)境中不建議使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
- 通過 npm 使用 React
- 使用 create-react-app 快速構(gòu)建 React 開發(fā)環(huán)境
2.3React render 渲染
屏幕輸出:Hello, React
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 使用cdn 上的React CDN庫(kù)-->
<!-- react.min.js - React 的核心庫(kù) -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!-- react-dom.min.js - 提供與 DOM 相關(guān)的功能 -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- babel.min.js - Babel 可以將 ES6 代碼轉(zhuǎn)為 ES5 代碼 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<!-- React render 渲染-->
<script type="text/babel">
ReactDOM.render(<h1>Hello, React </h1>,
document.getElementById('root')
);
</script>
</body>
</html>
3.React JSX
React 使用 JSX 來替代常規(guī)的 JavaScript扩淀。
1.React JSX簡(jiǎn)介
JSX:JavaScript XML楔敌,一種類似于XML的JS擴(kuò)展語法。也可以理解成:符合 XML 規(guī)范的 JS 語法驻谆。
JSX語法的本質(zhì):以 React.createElement 的形式來實(shí)現(xiàn)的卵凑,并沒有直接把 用戶寫的 HTML代碼,渲染到頁(yè)面上胜臊。使用babel轉(zhuǎn)換工具將 JSX語法 轉(zhuǎn)換為 JS語法勺卢。
我們不需要一定使用 JSX,但它有以下優(yōu)點(diǎn):
- JSX 執(zhí)行更快区端,因?yàn)樗诰幾g為 JavaScript 代碼后進(jìn)行了優(yōu)化值漫。
- 它是類型安全的,在編譯過程中就能發(fā)現(xiàn)錯(cuò)誤织盼。
- 使用 JSX 編寫模板更加簡(jiǎn)單快速杨何。
const element = <h1>Hello, world!</h1>;
這種看起來可能有些奇怪的標(biāo)簽語法既不是字符串也不是 HTML酱塔。
它被稱為 JSX, 一種 JavaScript 的語法擴(kuò)展危虱。 我們推薦在 React 中使用 JSX 來描述用戶界面羊娃。
JSX 是在 JavaScript 內(nèi)部實(shí)現(xiàn)的。
2.JSX的基本語法
(1)在 JSX內(nèi)部 寫 JS代碼:如果要在 JSX 語法內(nèi)部埃跷,書寫 JS 代碼蕊玷,那么,所有的JS代碼必須寫到 {} 的內(nèi)部弥雹。在{}內(nèi)部垃帅,可以寫任何符合JS規(guī)范的代碼。
例如:
var myTitle = '這是使用變量定義的 tilte 值'
// 使用JSX語法 創(chuàng)建虛擬DOM對(duì)象
var vDom = (
<div>
Hello, React!
<h2 title={myTitle + 'vae'}>這是標(biāo)題</h2>
</div>
);
(2)當(dāng)編譯引擎在編譯JSX代碼的時(shí)候剪勿,如果遇到了<贸诚,會(huì)把它當(dāng)作 HTML代碼 去編譯;如果遇到了 {}厕吉, 會(huì)把方括號(hào)里面的代碼當(dāng)作 普通JS代碼 去編譯酱固。
(3)在JSX中,如果要為元素添加class屬性头朱,則必須寫成className运悲,因?yàn)?class在ES6中是一個(gè)關(guān)鍵字;和class類似项钮,label標(biāo)簽的 for 屬性需要替換為 htmlFor班眯。
代碼舉例:
// 使用JSX語法 創(chuàng)建虛擬DOM對(duì)象
var vDom = (
<div>
Hello, React!
<p className="qianguyihao">千古壹號(hào)</p>
<label htmlFor="" />
</div>
);
(4)在JSX創(chuàng)建DOM的時(shí)候,所有的節(jié)點(diǎn)寄纵,必須有唯一的根元素進(jìn)行包裹鳖敷。
(5)如果要寫注釋,注釋必須放到 {} 內(nèi)部程拭。例如:
// 使用JSX語法 創(chuàng)建虛擬DOM對(duì)象
var vDom = (
// 這一行是注釋
<div>
Hello, React!
<p className="qianguyihao">千古壹號(hào)</p>
{/*這一行也是注釋 */}
</div>
);
最后定踱,再舉個(gè)例子:
<!DOCTYPE html>
<html lang="">
<head>
<meta />
<meta />
<meta />
<title>Document</title>
</head>
<body>
<!-- 引入React相關(guān)的js庫(kù) -->
<script type="text/javascript" src="./libs/react.js"></script>
<script type="text/javascript" src="./libs/react-dom.js"></script>
<script type="text/javascript" src="./libs/babel.min.js"></script>
<div id="app"></div>
<!-- 注意,這一行的 type 是寫 "text/babel"恃鞋,而不是 "text/javascript" -->
<script type="text/babel">
//頁(yè)面中的真實(shí)容器元素
var containDiv = document.getElementById("app");
var arr = []
for (var i = 0; i < 6; i++) {
var p = <p className="myp" key={i}>這個(gè)是p標(biāo)簽</p> // 注意這個(gè)地方的寫法: key = {i}
arr.push(p)
}
//1崖媚、使用JSX語法 創(chuàng)建虛擬DOM對(duì)象
var vDom = (
<div>
Hello, React!
{arr}
</div>
);
//2、渲染虛擬DOM對(duì)象
ReactDOM.render(vDom, containDiv); // 參數(shù)1:虛擬DOM對(duì)象恤浪;參數(shù)2:頁(yè)面中的容器
</script>
</body>
</html>
4.React 組件 狀態(tài)(State&props) 生命周期詳解
React 把組件看成是一個(gè)狀態(tài)機(jī)(State Machines)畅哑。通過與用戶的交互,實(shí)現(xiàn)不同狀態(tài)水由,然后渲染 UI荠呐,讓用戶界面和數(shù)據(jù)保持一致。
React 里,只需更新組件的 state泥张,然后根據(jù)新的 state 重新渲染用戶界面(不要操作 DOM)呵恢。
- 創(chuàng)建組件的第一種方式:在React中,構(gòu)造函數(shù)就是一個(gè)最基本的組件媚创。如果想要把組件放到頁(yè)面中渗钉,可以把構(gòu)造函數(shù)的名稱當(dāng)作組件的名稱,以 HTML標(biāo)簽形式引入頁(yè)面中即可钞钙。
- 創(chuàng)建組件的第二種方式:使用 class 關(guān)鍵字
使用 function 創(chuàng)建的組件鳄橘,叫做【無狀態(tài)組件】;使用 class 創(chuàng)建的組件芒炼,叫做【有狀態(tài)組件】瘫怜。
本質(zhì)區(qū)別:
有狀態(tài)組件和無狀態(tài)組件,最本質(zhì)的區(qū)別焕议,就是有無 state 屬性宝磨。同時(shí)弧关, class 創(chuàng)建的組件盅安,有自己的生命周期函數(shù),但是世囊,function 創(chuàng)建的 組件别瞭,沒有自己的生命周期函數(shù)。
state 和 props 主要的區(qū)別在于 props 是不可變的株憾,而 state 可以根據(jù)與用戶交互來改變蝙寨。這就是為什么有些容器組件需要定義 state 來更新和修改數(shù)據(jù)。 而子組件只能通過 props 來傳遞數(shù)據(jù)嗤瞎。
組件API
設(shè)置狀態(tài):setState
替換狀態(tài):replaceState
設(shè)置屬性:setProps
替換屬性:replaceProps
強(qiáng)制更新:forceUpdate
獲取DOM節(jié)點(diǎn):findDOMNode
判斷組件掛載狀態(tài):isMounted
組件的生命周期可分成三個(gè)狀態(tài):
在組件創(chuàng)建墙歪、到加載到頁(yè)面上運(yùn)行、以及組件被銷毀的過程中贝奇,總是伴隨著各種各樣的事件虹菲,這些在組件特定時(shí)期,觸發(fā)的事件統(tǒng)稱為組件的生命周期掉瞳。
- Mounting:已插入真實(shí) DOM
- Updating:正在被重新渲染
- Unmounting:已移出真實(shí) DOM
生命周期的方法有:
- componentWillMount 在渲染前調(diào)用,在客戶端也在服務(wù)端毕源。
- componentDidMount : 在第一次渲染后調(diào)用,只在客戶端陕习。之后組件已經(jīng)生成了對(duì)應(yīng)的DOM結(jié)構(gòu)霎褐,可以通過this.getDOMNode()來進(jìn)行訪問。 如果你想和其他JavaScript框架一起使用该镣,可以在這個(gè)方法中調(diào)用setTimeout, setInterval或者發(fā)送AJAX請(qǐng)求等操作(防止異步操作阻塞UI)冻璃。
- componentWillReceiveProps 在組件接收到一個(gè)新的 prop (更新后)時(shí)被調(diào)用。這個(gè)方法在初始化render時(shí)不會(huì)被調(diào)用。
- shouldComponentUpdate 返回一個(gè)布爾值省艳。在組件接收到新的props或者state時(shí)被調(diào)用歌粥。在初始化時(shí)或者使用forceUpdate時(shí)不被調(diào)用。
可以在你確認(rèn)不需要更新組件時(shí)使用拍埠。 - componentWillUpdate在組件接收到新的props或者state但還沒有render時(shí)被調(diào)用失驶。在初始化時(shí)不會(huì)被調(diào)用。
- componentDidUpdate 在組件完成更新后立即調(diào)用枣购。在初始化時(shí)不會(huì)被調(diào)用嬉探。
- componentWillUnmount在組件從 DOM 中移除之前立刻被調(diào)用。
1.組件創(chuàng)建階段
組件創(chuàng)建階段的生命周期函數(shù)棉圈,有一個(gè)顯著的特點(diǎn):創(chuàng)建階段的生命周期函數(shù)涩堤,在組件的一輩子中,只執(zhí)行一次分瘾。
- getDefaultProps
初始化 props 屬性默認(rèn)值胎围。
- getInitialState
初始化組件的私有數(shù)據(jù)。因?yàn)?state 是定義在組件的 constructor 構(gòu)造器當(dāng)中的德召,只要new 了 class類白魂,必然會(huì)調(diào)用 constructor構(gòu)造器。
- componentWillMount()
組件將要被掛載上岗。此時(shí)還沒有開始渲染虛擬DOM福荸。
在這個(gè)階段,不能去操作DOM元素肴掷,但可以操作屬性敬锐、狀態(tài)、function呆瞻。相當(dāng)于 Vue 中的Create()函數(shù)台夺。
- render()
第一次開始渲染真正的虛擬DOM。當(dāng)render執(zhí)行完痴脾,內(nèi)存中就有了完整的虛擬DOM了颤介。
意思是,此時(shí)明郭,虛擬DOM在內(nèi)存中創(chuàng)建好了买窟,但是還沒有掛在到頁(yè)面上。
在這個(gè)函數(shù)內(nèi)部薯定,不能去操作DOM元素始绍,因?yàn)檫€沒return之前,虛擬DOM還沒有創(chuàng)建话侄;當(dāng)return執(zhí)行完畢后亏推,虛擬DOM就創(chuàng)建好了学赛,但是還沒有掛在到頁(yè)面上。
- componentDidMount()
當(dāng)組件(虛擬DOM)掛載到頁(yè)面之后吞杭,會(huì)進(jìn)入這個(gè)生命周期函數(shù)盏浇。
只要進(jìn)入到這個(gè)生命周期函數(shù),則必然說明芽狗,頁(yè)面上已經(jīng)有可見的DOM元素了绢掰。此時(shí),組件已經(jīng)顯示到了頁(yè)面上童擎,state上的數(shù)據(jù)滴劲、內(nèi)存中的虛擬DOM、以及瀏覽器中的頁(yè)面顾复,已經(jīng)完全保持一致了班挖。
當(dāng)這個(gè)方法執(zhí)行完,組件就進(jìn)入都了 運(yùn)行中 的狀態(tài)芯砸。所以說萧芙,componentDidMount 是創(chuàng)建階段的最后一個(gè)函數(shù)。
在這個(gè)函數(shù)中假丧,我們可以放心的去 操作 頁(yè)面上你需要使用的 DOM 元素了双揪。如果我們想操作DOM元素,最早只能在 componentDidMount 中進(jìn)行虎谢。相當(dāng)于 Vue 中的 mounted() 函數(shù)
2盟榴、組件運(yùn)行階段
有一個(gè)顯著的特點(diǎn),根據(jù)組件的state和props的改變婴噩,有選擇性的觸發(fā)0次或多次。
- componentWillReceiveProps()
組件將要接收新屬性羽德。只有當(dāng)父組件中几莽,通過某些事件,重新修改了 傳遞給 子組件的 props 數(shù)據(jù)之后宅静,才會(huì)觸發(fā)這個(gè)鉤子函數(shù)章蚣。
- shouldComponentUpdate()
判斷組件是否需要被更新。此時(shí)姨夹,組件尚未被更新纤垂,但是,state 和 props 肯定是最新的磷账。
- componentWillUpdate()
組件將要被更新峭沦。此時(shí),組件還沒有被更新逃糟,在進(jìn)入到這個(gè)生命周期函數(shù)的時(shí)候吼鱼,內(nèi)存中的虛擬DOM還是舊的蓬豁,頁(yè)面上的 DOM 元素也是舊的。(也就是說菇肃,此時(shí)操作的是舊的 DOM元素)
- render
此時(shí)地粪,又要根據(jù)最新的 state 和 props,重新渲染一棵內(nèi)存中的 虛擬DOM樹琐谤。當(dāng) render 調(diào)用完畢蟆技,內(nèi)存中的舊DOM樹,已經(jīng)被新DOM樹替換了斗忌!此時(shí)付魔,虛擬DOM樹已經(jīng)和組件的 state 保持一致了,都是最新的飞蹂;但是頁(yè)面還是舊的几苍。
- componentDidUpdate
此時(shí),組件完成更新陈哑,頁(yè)面被重新渲染妻坝。此時(shí),state惊窖、虛擬DOM 和 頁(yè)面已經(jīng)完全保持同步刽宪。
3、組件銷毀階段
一輩子只執(zhí)行一次界酒。
- componentWillUnmount: 組件將要被卸載圣拄。此時(shí)組件還可以正常使用。
生命周期對(duì)比:
組件生命周期的執(zhí)行順序總結(jié)
1毁欣、Mounting:
constructor()
componentWillMount()
render()
componentDidMount()
2庇谆、Updating:
componentWillReceiveProps(nextProps):接收父組件傳遞過來的屬性
shouldComponentUpdate(nextProps, nextState):一旦調(diào)用 setState,就會(huì)觸發(fā)這個(gè)方法凭疮。方法默認(rèn) return true饭耳;如果 return false,后續(xù)的方法就不會(huì)走了执解。
componentWillUpdate(nextProps, nextState)
render()
componentDidUpdate(prevProps, prevState)
3寞肖、Unmounting:
- componentWillUnmount()
5.React 事件處理
React 元素的事件處理和 DOM 元素類似。但是有一點(diǎn)語法上的不同:
React 事件綁定屬性的命名采用駝峰式寫法衰腌,而不是小寫新蟆。
如果采用 JSX 的語法你需要傳入一個(gè)函數(shù)作為事件處理函數(shù),而不是一個(gè)字符串(DOM 元素的寫法)
//HTML 通常寫法是:
<button onclick="activateLasers()">
激活按鈕
</button>
//React 中寫法為:
<button onClick={activateLasers}>
激活按鈕
</button>