1.RN簡介
React Native
(簡稱RN)是Facebook于2015年4月開源的跨平臺移動應(yīng)用開發(fā)框架,是Facebook早先開源的JS框架React
在原生移動應(yīng)用平臺的衍生產(chǎn)物,目前支持iOS和安卓兩大平臺。RN使用Javascript
語言,類似于HTML
的JSX
,以及CSS
來開發(fā)移動應(yīng)用,因此熟悉Web前端開發(fā)的技術(shù)人員只需很少的學(xué)習(xí)就可以進(jìn)入移動應(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ā)特點:
- 一次學(xué)習(xí),隨處編寫:使用React Native可以為iOS和Android操作系統(tǒng)開發(fā)應(yīng)用程序,不同平臺上的代碼根據(jù)平臺會有一些微小的區(qū)別。
- 混合開發(fā):React Native代碼開發(fā)的模塊與原生代碼開發(fā)的模塊可以雙向通信、無縫銜接;
- 高效的移動應(yīng)用開發(fā):
(1)獨特的UI實現(xiàn)框架
(2)組件化開發(fā)
(3)跨平臺移植代碼迅速
(4)自動匹配不同屏幕大小的手機(jī)
- 高效的移動應(yīng)用開發(fā)調(diào)試
- 高效的應(yīng)用熱更新
- 有效降低移動應(yīng)用安裝包體積
- 學(xué)習(xí)門檻低、開發(fā)難度低
使用React Native開發(fā)的代價
為了得到React Native開發(fā)的優(yōu)點,使用React Native開發(fā)的APP也需要付出一定的代價。
- (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)換,以實現(xiàn)了頁面組件高效更新的前端表現(xiàn)。
現(xiàn)在最新版本是0.59React Native中文網(wǎng)
React Native
與React
的關(guān)系及特點:React
是基礎(chǔ)框架,是一套基礎(chǔ)設(shè)計實現(xiàn)理念,開發(fā)者不能直接使用它來開發(fā)移動應(yīng)用或網(wǎng)頁。在React
之上發(fā)展出了React.js
框架用來開發(fā)網(wǎng)頁,發(fā)展出來React Native
用來開發(fā)移動應(yīng)用。底層原理是相同的,都是使用js實現(xiàn)虛擬dom樹來驅(qū)動頁面的渲染,react是驅(qū)動HTML dom的渲染,react native是驅(qū)動原生組件的渲染。
React.js
:目的 是為了使前端的V層更具組件化,能更好的復(fù)用,它能夠使用簡單的html標(biāo)簽創(chuàng)建更多的自定義組件標(biāo)簽,內(nèi)部綁定事件,同時可以讓你從操作dom中解脫出來,只需要操作數(shù)據(jù)就會改變相應(yīng)的dom。
二者都是基于組件(component
)開發(fā),然后組件和組件之間通過props
傳遞方法,每個組件都有一個狀態(tài)(state)
,當(dāng)某個方法改變了這個狀態(tài)值時,整個組件就會重繪,從而達(dá)到刷新。另外,說到重繪就要提到虛擬dom
了,就是用js模擬dom
結(jié)構(gòu),等整個組件的dom
更新完畢,它會有一個diff
的過程,對比出哪些組件發(fā)生了變化,然后才渲染到頁面,簡單來說只更新了相比之前改變了的部分,而不是全部刷新,所以效率很高。
虛擬DOM(Virtual DOM)
的機(jī)制:在瀏覽器端用Javascript
實現(xiàn)了一套DOM API
。基于React
進(jìn)行開發(fā)時所有的DOM
構(gòu)造都是通過虛擬DOM
進(jìn)行,每當(dāng)數(shù)據(jù)變化時,React都會重新構(gòu)建整個DOM樹,然后React將當(dāng)前整個DOM樹和上一次的DOM樹進(jìn)行對比,得到DOM結(jié)構(gòu)的區(qū)別,然后僅僅將需要變化的部分進(jìn)行實際的瀏覽器DOM更新。而且React能夠批處理虛擬DOM的刷新,在一個事件循環(huán)(Event Loop)內(nèi)的兩次數(shù)據(jù)變化會被合并。
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 簡介
React
是一個聲明式,高效且靈活的用于構(gòu)建用戶界面的 JavaScript 庫。使用 React 可以將一些簡短、獨立的代碼片段組合成復(fù)雜的 UI 界面,這些代碼片段被稱作“組件”。
React
特點
- 1.聲明式設(shè)計 ?
React
采用聲明范式,可以輕松描述應(yīng)用。 - 2.高效 ?
React
通過對DOM的模擬,最大限度地減少與DOM的交互。 - 3.靈活 ?
React
可以與已知的庫或框架很好地配合。 - 4.JSX ?
JSX
是JavaScript
語法的擴(kuò)展。React 開發(fā)不一定使用 JSX ,但我們建議使用它。 - 5.組件 ? 通過
React
構(gòu)建組件,使得代碼更加容易得到復(fù)用,能夠很好的應(yīng)用在大項目的開發(fā)中。 - 6.單向響應(yīng)的數(shù)據(jù)流 ?
React
實現(xiàn)了單向響應(yīng)的數(shù)據(jù)流,從而減少了重復(fù)代碼,這也是它為什么比傳統(tǒng)數(shù)據(jù)綁定更簡單。
2.2 React使用
1.React 環(huán)境配置安裝
- 使用 React CDN 庫
<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庫-->
<!-- react.min.js - React 的核心庫 -->
<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簡介
JSX:JavaScript XML,一種類似于XML的JS擴(kuò)展語法。也可以理解成:符合 XML 規(guī)范的 JS 語法。
JSX語法的本質(zhì):以 React.createElement 的形式來實現(xiàn)的,并沒有直接把 用戶寫的 HTML代碼,渲染到頁面上。使用babel轉(zhuǎn)換工具將 JSX語法 轉(zhuǎn)換為 JS語法。
我們不需要一定使用 JSX,但它有以下優(yōu)點:
- JSX 執(zhí)行更快,因為它在編譯為 JavaScript 代碼后進(jìn)行了優(yōu)化。
- 它是類型安全的,在編譯過程中就能發(fā)現(xiàn)錯誤。
- 使用 JSX 編寫模板更加簡單快速。
const element = <h1>Hello, world!</h1>;
這種看起來可能有些奇怪的標(biāo)簽語法既不是字符串也不是 HTML。
它被稱為 JSX, 一種 JavaScript 的語法擴(kuò)展。 我們推薦在 React 中使用 JSX 來描述用戶界面。
JSX 是在 JavaScript 內(nèi)部實現(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對象
var vDom = (
<div>
Hello, React!
<h2 title={myTitle + 'vae'}>這是標(biāo)題</h2>
</div>
);
(2)當(dāng)編譯引擎在編譯JSX代碼的時候,如果遇到了<,會把它當(dāng)作 HTML代碼 去編譯;如果遇到了 {}, 會把方括號里面的代碼當(dāng)作 普通JS代碼 去編譯。
(3)在JSX中,如果要為元素添加class屬性,則必須寫成className,因為 class在ES6中是一個關(guān)鍵字;和class類似,label標(biāo)簽的 for 屬性需要替換為 htmlFor。
代碼舉例:
// 使用JSX語法 創(chuàng)建虛擬DOM對象
var vDom = (
<div>
Hello, React!
<p className="qianguyihao">千古壹號</p>
<label htmlFor="" />
</div>
);
(4)在JSX創(chuàng)建DOM的時候,所有的節(jié)點,必須有唯一的根元素進(jìn)行包裹。
(5)如果要寫注釋,注釋必須放到 {} 內(nèi)部。例如:
// 使用JSX語法 創(chuàng)建虛擬DOM對象
var vDom = (
// 這一行是注釋
<div>
Hello, React!
<p className="qianguyihao">千古壹號</p>
{/*這一行也是注釋 */}
</div>
);
最后,再舉個例子:
<!DOCTYPE html>
<html lang="">
<head>
<meta />
<meta />
<meta />
<title>Document</title>
</head>
<body>
<!-- 引入React相關(guān)的js庫 -->
<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">
//頁面中的真實容器元素
var containDiv = document.getElementById("app");
var arr = []
for (var i = 0; i < 6; i++) {
var p = <p className="myp" key={i}>這個是p標(biāo)簽</p> // 注意這個地方的寫法: key = {i}
arr.push(p)
}
//1、使用JSX語法 創(chuàng)建虛擬DOM對象
var vDom = (
<div>
Hello, React!
{arr}
</div>
);
//2、渲染虛擬DOM對象
ReactDOM.render(vDom, containDiv); // 參數(shù)1:虛擬DOM對象;參數(shù)2:頁面中的容器
</script>
</body>
</html>
4.React 組件 狀態(tài)(State&props) 生命周期詳解
React 把組件看成是一個狀態(tài)機(jī)(State Machines)。通過與用戶的交互,實現(xiàn)不同狀態(tài),然后渲染 UI,讓用戶界面和數(shù)據(jù)保持一致。
React 里,只需更新組件的 state,然后根據(jù)新的 state 重新渲染用戶界面(不要操作 DOM)。
- 創(chuàng)建組件的第一種方式:在React中,構(gòu)造函數(shù)就是一個最基本的組件。如果想要把組件放到頁面中,可以把構(gòu)造函數(shù)的名稱當(dāng)作組件的名稱,以 HTML標(biāo)簽形式引入頁面中即可。
- 創(chuàng)建組件的第二種方式:使用 class 關(guān)鍵字
使用 function 創(chuàng)建的組件,叫做【無狀態(tài)組件】;使用 class 創(chuàng)建的組件,叫做【有狀態(tài)組件】。
本質(zhì)區(qū)別:
有狀態(tài)組件和無狀態(tài)組件,最本質(zhì)的區(qū)別,就是有無 state 屬性。同時, 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é)點:findDOMNode
判斷組件掛載狀態(tài):isMounted
組件的生命周期可分成三個狀態(tài):
在組件創(chuàng)建、到加載到頁面上運(yùn)行、以及組件被銷毀的過程中,總是伴隨著各種各樣的事件,這些在組件特定時期,觸發(fā)的事件統(tǒng)稱為組件的生命周期。
- Mounting:已插入真實 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真實 DOM
生命周期的方法有:
- componentWillMount 在渲染前調(diào)用,在客戶端也在服務(wù)端。
- componentDidMount : 在第一次渲染后調(diào)用,只在客戶端。之后組件已經(jīng)生成了對應(yīng)的DOM結(jié)構(gòu),可以通過this.getDOMNode()來進(jìn)行訪問。 如果你想和其他JavaScript框架一起使用,可以在這個方法中調(diào)用setTimeout, setInterval或者發(fā)送AJAX請求等操作(防止異步操作阻塞UI)。
- componentWillReceiveProps 在組件接收到一個新的 prop (更新后)時被調(diào)用。這個方法在初始化render時不會被調(diào)用。
- shouldComponentUpdate 返回一個布爾值。在組件接收到新的props或者state時被調(diào)用。在初始化時或者使用forceUpdate時不被調(diào)用。
可以在你確認(rèn)不需要更新組件時使用。 - componentWillUpdate在組件接收到新的props或者state但還沒有render時被調(diào)用。在初始化時不會被調(diào)用。
- componentDidUpdate 在組件完成更新后立即調(diào)用。在初始化時不會被調(diào)用。
- componentWillUnmount在組件從 DOM 中移除之前立刻被調(diào)用。
1.組件創(chuàng)建階段
組件創(chuàng)建階段的生命周期函數(shù),有一個顯著的特點:創(chuàng)建階段的生命周期函數(shù),在組件的一輩子中,只執(zhí)行一次。
- getDefaultProps
初始化 props 屬性默認(rèn)值。
- getInitialState
初始化組件的私有數(shù)據(jù)。因為 state 是定義在組件的 constructor 構(gòu)造器當(dāng)中的,只要new 了 class類,必然會調(diào)用 constructor構(gòu)造器。
- componentWillMount()
組件將要被掛載。此時還沒有開始渲染虛擬DOM。
在這個階段,不能去操作DOM元素,但可以操作屬性、狀態(tài)、function。相當(dāng)于 Vue 中的Create()函數(shù)。
- render()
第一次開始渲染真正的虛擬DOM。當(dāng)render執(zhí)行完,內(nèi)存中就有了完整的虛擬DOM了。
意思是,此時,虛擬DOM在內(nèi)存中創(chuàng)建好了,但是還沒有掛在到頁面上。
在這個函數(shù)內(nèi)部,不能去操作DOM元素,因為還沒return之前,虛擬DOM還沒有創(chuàng)建;當(dāng)return執(zhí)行完畢后,虛擬DOM就創(chuàng)建好了,但是還沒有掛在到頁面上。
- componentDidMount()
當(dāng)組件(虛擬DOM)掛載到頁面之后,會進(jìn)入這個生命周期函數(shù)。
只要進(jìn)入到這個生命周期函數(shù),則必然說明,頁面上已經(jīng)有可見的DOM元素了。此時,組件已經(jīng)顯示到了頁面上,state上的數(shù)據(jù)、內(nèi)存中的虛擬DOM、以及瀏覽器中的頁面,已經(jīng)完全保持一致了。
當(dāng)這個方法執(zhí)行完,組件就進(jìn)入都了 運(yùn)行中 的狀態(tài)。所以說,componentDidMount 是創(chuàng)建階段的最后一個函數(shù)。
在這個函數(shù)中,我們可以放心的去 操作 頁面上你需要使用的 DOM 元素了。如果我們想操作DOM元素,最早只能在 componentDidMount 中進(jìn)行。相當(dāng)于 Vue 中的 mounted() 函數(shù)
2、組件運(yùn)行階段
有一個顯著的特點,根據(jù)組件的state和props的改變,有選擇性的觸發(fā)0次或多次。
- componentWillReceiveProps()
組件將要接收新屬性。只有當(dāng)父組件中,通過某些事件,重新修改了 傳遞給 子組件的 props 數(shù)據(jù)之后,才會觸發(fā)這個鉤子函數(shù)。
- shouldComponentUpdate()
判斷組件是否需要被更新。此時,組件尚未被更新,但是,state 和 props 肯定是最新的。
- componentWillUpdate()
組件將要被更新。此時,組件還沒有被更新,在進(jìn)入到這個生命周期函數(shù)的時候,內(nèi)存中的虛擬DOM還是舊的,頁面上的 DOM 元素也是舊的。(也就是說,此時操作的是舊的 DOM元素)
- render
此時,又要根據(jù)最新的 state 和 props,重新渲染一棵內(nèi)存中的 虛擬DOM樹。當(dāng) render 調(diào)用完畢,內(nèi)存中的舊DOM樹,已經(jīng)被新DOM樹替換了!此時,虛擬DOM樹已經(jīng)和組件的 state 保持一致了,都是最新的;但是頁面還是舊的。
- componentDidUpdate
此時,組件完成更新,頁面被重新渲染。此時,state、虛擬DOM 和 頁面已經(jīng)完全保持同步。
3、組件銷毀階段
一輩子只執(zhí)行一次。
- componentWillUnmount: 組件將要被卸載。此時組件還可以正常使用。
生命周期對比:
組件生命周期的執(zhí)行順序總結(jié)
1、Mounting:
constructor()
componentWillMount()
render()
componentDidMount()
2、Updating:
componentWillReceiveProps(nextProps):接收父組件傳遞過來的屬性
shouldComponentUpdate(nextProps, nextState):一旦調(diào)用 setState,就會觸發(fā)這個方法。方法默認(rèn) return true;如果 return false,后續(xù)的方法就不會走了。
componentWillUpdate(nextProps, nextState)
render()
componentDidUpdate(prevProps, prevState)
3、Unmounting:
- componentWillUnmount()
5.React 事件處理
React 元素的事件處理和 DOM 元素類似。但是有一點語法上的不同:
React 事件綁定屬性的命名采用駝峰式寫法,而不是小寫。
如果采用 JSX 的語法你需要傳入一個函數(shù)作為事件處理函數(shù),而不是一個字符串(DOM 元素的寫法)
//HTML 通常寫法是:
<button onclick="activateLasers()">
激活按鈕
</button>
//React 中寫法為:
<button onClick={activateLasers}>
激活按鈕
</button>