您好,登錄后才能下訂單哦!
這篇文章主要介紹“React的相關(guān)知識(shí)點(diǎn)有哪些”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“React的相關(guān)知識(shí)點(diǎn)有哪些”文章能幫助大家解決問題。
輕量級(jí)的視圖層庫(kù)!A JavaScript library for building user interfaces
React不是一個(gè)完整的MVC框架,最多可以認(rèn)為是MVC中的V(View),甚至React并不非常認(rèn)可MVC開發(fā)模式;React 構(gòu)建頁(yè)面 UI 的庫(kù)。可以簡(jiǎn)單地理解為,React 將將界面分成了各個(gè)獨(dú)立的小塊,每一個(gè)塊就是組件,這些組件之間可以組合、嵌套,就成了我們的頁(yè)面。
React高性能的原理:
在Web開發(fā)中我們總需要將變化的數(shù)據(jù)實(shí)時(shí)反應(yīng)到UI上,這時(shí)就需要對(duì)DOM進(jìn)行操作。而復(fù)雜或頻繁的DOM操作通常是性能瓶頸產(chǎn)生的原因(如何進(jìn)行高性能的復(fù)雜DOM操作通常是衡量一個(gè)前端開發(fā)人員技能的重要指標(biāo))。
React為此引入了虛擬DOM(Virtual DOM)的機(jī)制:在瀏覽器端用Javascript實(shí)現(xiàn)了一套DOM API?;赗eact進(jìn)行開發(fā)時(shí)所有的DOM構(gòu)造都是通過(guò)虛擬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ì)被合并,例如你連續(xù)的先將節(jié)點(diǎn)內(nèi)容從A-B,B-A,React會(huì)認(rèn)為A變成B,然后又從B變成A UI不發(fā)生任何變化,而如果通過(guò)手動(dòng)控制,這種邏輯通常是極其復(fù)雜的。
盡管每一次都需要構(gòu)造完整的虛擬DOM樹,但是因?yàn)樘摂MDOM是內(nèi)存數(shù)據(jù),性能是極高的,部而對(duì)實(shí)際DOM進(jìn)行操作的僅僅是Diff分,因而能達(dá)到提高性能的目的。這樣,在保證性能的同時(shí),開發(fā)者將不再需要關(guān)注某個(gè)數(shù)據(jù)的變化如何更新到一個(gè)或多個(gè)具體的DOM元素,而只需要關(guān)心在任意一個(gè)數(shù)據(jù)狀態(tài)下,整個(gè)界面是如何Render的。
在react 16之后發(fā)布的一種react 核心算法,React Fiber是對(duì)核心算法的一次重新實(shí)現(xiàn)(官網(wǎng)說(shuō)法)。之前用的是diff算法。
在之前React中,更新過(guò)程是同步的,這可能會(huì)導(dǎo)致性能問題。
當(dāng)React決定要加載或者更新組件樹時(shí),會(huì)做很多事,比如調(diào)用各個(gè)組件的生命周期函數(shù),計(jì)算和比對(duì)Virtual DOM,最后更新DOM樹,這整個(gè)過(guò)程是同步進(jìn)行的,也就是說(shuō)只要一個(gè)加載或者更新過(guò)程開始,中途不會(huì)中斷。因?yàn)镴avaScript單線程的特點(diǎn),如果組件樹很大的時(shí)候,每個(gè)同步任務(wù)耗時(shí)太長(zhǎng),就會(huì)出現(xiàn)卡頓。
React Fiber的方法其實(shí)很簡(jiǎn)單——分片。把一個(gè)耗時(shí)長(zhǎng)的任務(wù)分成很多小片,每一個(gè)小片的運(yùn)行時(shí)間很短,雖然總時(shí)間依然很長(zhǎng),但是在每個(gè)小片執(zhí)行完之后,都給其他任務(wù)一個(gè)執(zhí)行的機(jī)會(huì),這樣唯一的線程就不會(huì)被獨(dú)占,其他任務(wù)依然有運(yùn)行的機(jī)會(huì)。
1、虛擬DOM
我們以前操作dom的方式是通過(guò)document.getElementById()的方式,這樣的過(guò)程實(shí)際上是先去讀取html的dom結(jié)構(gòu),將結(jié)構(gòu)轉(zhuǎn)換成變量,再進(jìn)行操作
而reactjs定義了一套變量形式的dom模型,一切操作和換算直接在變量中,這樣減少了操作真實(shí)dom,性能真實(shí)相當(dāng)?shù)母撸椭髁鱉VC框架有本質(zhì)的區(qū)別,并不和dom打交道
2、組件系統(tǒng)
react最核心的思想是將頁(yè)面中任何一個(gè)區(qū)域或者元素都可以看做一個(gè)組件 component
那么什么是組件呢?
組件指的就是同時(shí)包含了html、css、js、image元素的聚合體
使用react開發(fā)的核心就是將頁(yè)面拆分成若干個(gè)組件,并且react一個(gè)組件中同時(shí)耦合了css、js、image,這種模式整個(gè)顛覆了過(guò)去的傳統(tǒng)的方式
3、單向數(shù)據(jù)流
其實(shí)reactjs的核心內(nèi)容就是數(shù)據(jù)綁定,所謂數(shù)據(jù)綁定指的是只要將一些服務(wù)端的數(shù)據(jù)和前端頁(yè)面綁定好,開發(fā)者只關(guān)注實(shí)現(xiàn)業(yè)務(wù)就行了
4、JSX 語(yǔ)法
在vue中,我們使用render函數(shù)來(lái)構(gòu)建組件的dom結(jié)構(gòu)性能較高,因?yàn)槭∪チ瞬檎液途幾g模板的過(guò)程,但是在render中利用createElement創(chuàng)建結(jié)構(gòu)的時(shí)候代碼可讀性較低,較為復(fù)雜,此時(shí)可以利用jsx語(yǔ)法來(lái)在render中創(chuàng)建dom,解決這個(gè)問題,但是前提是需要使用工具來(lái)編譯jsx
react開發(fā)需要引入多個(gè)依賴文件:react.js、react-dom.js,分別又有開發(fā)版本和生產(chǎn)版本,create-react-app里已經(jīng)幫我們把這些東西都安裝好了。把通過(guò)CRA創(chuàng)建的工程目錄下的src目錄清空,然后在里面重新創(chuàng)建一個(gè)index.js. 寫入以下代碼:
// 從 react 的包當(dāng)中引入了 React。只要你要寫 React.js 組件就必須引入React, 因?yàn)閞eact里有一種語(yǔ)法叫JSX,稍后會(huì)講到JSX,要寫JSX,就必須引入Reactimport React from 'react'// ReactDOM 可以幫助我們把 React 組件渲染到頁(yè)面上去,沒有其它的作用了。它是從 react-dom 中引入的,而不是從 react 引入。import ReactDOM from 'react-dom'// ReactDOM里有一個(gè)render方法,功能就是把組件渲染并且構(gòu)造 DOM 樹,然后插入到頁(yè)面上某個(gè)特定的元素上ReactDOM.render(// 這里就比較奇怪了,它并不是一個(gè)字符串,看起來(lái)像是純 HTML 代碼寫在 JavaScript 代碼里面。語(yǔ)法錯(cuò)誤嗎?這并不是合法的 JavaScript 代碼, “在 JavaScript 寫的標(biāo)簽的”語(yǔ)法叫 JSX- JavaScript XML。 <h2>歡迎進(jìn)入React的世界</h2>,// 渲染到哪里 document.getElementById('root'))
如果代碼多了之后,不可能一直在render方法里寫,所以就需要把里面的代碼提出來(lái),定義一個(gè)變量,像這樣:
import React from 'react'import ReactDOM from 'react-dom'// 這里感覺又不習(xí)慣了?這是在用JSX定義一下react元素const app = <h2>歡迎進(jìn)入React的世界</h2>ReactDOM.render(
app,
document.getElementById('root'))
由于元素沒有辦法傳遞參數(shù),所以我們就需要把之前定義的變量改為一個(gè)方法,讓這個(gè)方法去return一個(gè)元素:
import React from 'react'import ReactDOM from 'react-dom'// 特別注意這里的寫法,如果要在JSX里寫js表達(dá)式(只能是表達(dá)式,不能流程控制),就需要加 {},包括注釋也是一樣,并且可以多層嵌套const app = (props) => <h2>歡迎進(jìn)入{props.name}的世界</h2>ReactDOM.render(
app({
name: 'react'
}),
document.getElementById('root'))
這里我們定義的方法實(shí)際上也是react定義組件的第一種方式-定義函數(shù)式組件,這也是無(wú)狀態(tài)組件。但是這種寫法不符合react的jsx的風(fēng)格,更好的方式是使用以下方式進(jìn)行改造
import React from 'react'import ReactDOM from 'react-dom'const App = (props) => <h2>歡迎進(jìn)入{props.name}的世界</h2>ReactDOM.render(
// React組件的調(diào)用方式 <App name="react" />,
document.getElementById('root'))
這樣一個(gè)完整的函數(shù)式組件就定義好了。但要注意!注意!注意!組件名必須大寫,否則報(bào)錯(cuò)。
ES6的加入讓JavaScript直接支持使用class來(lái)定義一個(gè)類,react的第二種創(chuàng)建組件的方式就是使用的類的繼承,ES6 class是目前官方推薦的使用方式,它使用了ES6標(biāo)準(zhǔn)語(yǔ)法來(lái)構(gòu)建,看以下代碼:
import React from 'react'import ReactDOM from 'react-dom'class App extends React.Component {
render () {
return (
// 注意這里得用this.props.name, 必須用this.props <h2>歡迎進(jìn)入{this.props.name}的世界</h2>
)
}}ReactDOM.render(
<App name="react" />,
document.getElementById('root'))
運(yùn)行結(jié)果和之前完全一樣,因?yàn)镴S里沒有真正的class,這個(gè)class只是一個(gè)語(yǔ)法糖, 但二者的運(yùn)行機(jī)制底層運(yùn)行機(jī)制不一樣。
· 函數(shù)式組件是直接調(diào)用, 在前面的代碼里已經(jīng)有看到
· es6 class組件其實(shí)就是一個(gè)構(gòu)造器,每次使用組件都相當(dāng)于在實(shí)例化組件,像這樣:
import React from 'react'import ReactDOM from 'react-dom'class App extends React.Component {
render () {
return (
<h2>歡迎進(jìn)入{this.props.name}的世界</h2>
)
}}const app = new App({
name: 'react'}).render()ReactDOM.render(
app,
document.getElementById('root'))
在16以前的版本還支持這樣創(chuàng)建組件, 但現(xiàn)在的項(xiàng)目基本上不用
React.createClass({
render () {
return (
<div>{this.props.xxx}</div>
)
}})
將一個(gè)組件渲染到某一個(gè)節(jié)點(diǎn)里的時(shí)候,會(huì)將這個(gè)節(jié)點(diǎn)里原有內(nèi)容覆蓋
組件嵌套的方式就是將子組件寫入到父組件的模板中去,且react沒有Vue中的內(nèi)容分發(fā)機(jī)制(slot),所以我們?cè)谝粋€(gè)組件的模板中只能看到父子關(guān)系
// 從 react 的包當(dāng)中引入了 React 和 React.js 的組件父類 Component// 還引入了一個(gè)React.js里的一種特殊的組件 Fragmentimport React, { Component, Fragment } from 'react'import ReactDOM from 'react-dom'class Title extends Component {
render () {
return (
<h2>歡迎進(jìn)入React的世界</h2>
)
}}class Content extends Component {
render () {
return (
<p>React.js是一個(gè)構(gòu)建UI的庫(kù)</p>
)
}}/** 由于每個(gè)React組件只能有一個(gè)根節(jié)點(diǎn),所以要渲染多個(gè)組件的時(shí)候,需要在最外層包一個(gè)容器,如果使用div, 會(huì)生成多余的一層domclass App extends Component { render () { return ( <div> <Title /> <Content /> </div> ) }}**/// 如果不想生成多余的一層dom可以使用React提供的Fragment組件在最外層進(jìn)行包裹class App extends Component {
render () {
return (
<Fragment>
<Title />
<Content />
</Fragment>
)
}}ReactDOM.render(
<App/>,
document.getElementById('root'))
#JSX 原理
要明白JSX的原理,需要先明白如何用 JavaScript 對(duì)象來(lái)表現(xiàn)一個(gè) DOM 元素的結(jié)構(gòu)?
看下面的DOM結(jié)構(gòu)
<div class='app' id='appRoot'>
<h2 class='title'>歡迎進(jìn)入React的世界</h2>
<p>
React.js 是一個(gè)幫助你構(gòu)建頁(yè)面 UI 的庫(kù)
</p></div>
上面這個(gè) HTML 所有的信息我們都可以用 JavaScript 對(duì)象來(lái)表示:
{
tag: 'div',
attrs: { className: 'app', id: 'appRoot'},
children: [
{
tag: 'h2',
attrs: { className: 'title' },
children: ['歡迎進(jìn)入React的世界']
},
{
tag: 'p',
attrs: null,
children: ['React.js 是一個(gè)構(gòu)建頁(yè)面 UI 的庫(kù)']
}
]}
但是用 JavaScript 寫起來(lái)太長(zhǎng)了,結(jié)構(gòu)看起來(lái)又不清晰,用 HTML 的方式寫起來(lái)就方便很多了。
于是 React.js 就把 JavaScript 的語(yǔ)法擴(kuò)展了一下,讓 JavaScript 語(yǔ)言能夠支持這種直接在 JavaScript 代碼里面編寫類似 HTML 標(biāo)簽結(jié)構(gòu)的語(yǔ)法,這樣寫起來(lái)就方便很多了。編譯的過(guò)程會(huì)把類似 HTML 的 JSX 結(jié)構(gòu)轉(zhuǎn)換成 JavaScript 的對(duì)象結(jié)構(gòu)。
下面代碼:
import React from 'react'import ReactDOM from 'react-dom'class App extends React.Component {
render () {
return (
<div className='app' id='appRoot'>
<h2 className='title'>歡迎進(jìn)入React的世界</h2>
<p>
React.js 是一個(gè)構(gòu)建頁(yè)面 UI 的庫(kù)
</p>
</div>
)
}}ReactDOM.render(
<App />,
document.getElementById('root'))
編譯之后將得到這樣的代碼:
import React from 'react'import ReactDOM from 'react-dom'class App extends React.Component {
render () {
return (
React.createElement(
"div",
{
className: 'app',
id: 'appRoot'
},
React.createElement(
"h2",
{ className: 'title' },
"歡迎進(jìn)入React的世界"
),
React.createElement(
"p",
null,
"React.js 是一個(gè)構(gòu)建頁(yè)面 UI 的庫(kù)"
)
)
)
}}ReactDOM.render(
React.createElement(App),
document.getElementById('root'))
React.createElement 會(huì)構(gòu)建一個(gè) JavaScript 對(duì)象來(lái)描述你 HTML 結(jié)構(gòu)的信息,包括標(biāo)簽名、屬性、還有子元素等, 語(yǔ)法為
React.createElement(
type,
[props],
[...children])
所謂的 JSX 其實(shí)就是 JavaScript 對(duì)象,所以使用 React 和 JSX 的時(shí)候一定要經(jīng)過(guò)編譯的過(guò)程:
JSX —使用react構(gòu)造組件,bable進(jìn)行編譯—> JavaScript對(duì)象 — ReactDOM.render()—>DOM元素 —>插入頁(yè)面
· 行內(nèi)樣式
想給虛擬dom添加行內(nèi)樣式,需要使用表達(dá)式傳入樣式對(duì)象的方式來(lái)實(shí)現(xiàn):
// 注意這里的兩個(gè)括號(hào),第一個(gè)表示我們?cè)谝狫SX里插入JS了,第二個(gè)是對(duì)象的括號(hào) <p style={{color:'red', fontSize:'14px'}}>Hello world</p>
行內(nèi)樣式需要寫入一個(gè)樣式對(duì)象,而這個(gè)樣式對(duì)象的位置可以放在很多地方,例如render函數(shù)里、組件原型上、外鏈js文件中
· 使用class
React推薦我們使用行內(nèi)樣式,因?yàn)镽eact覺得每一個(gè)組件都是一個(gè)獨(dú)立的整體
其實(shí)我們大多數(shù)情況下還是大量的在為元素添加類名,但是需要注意的是,class需要寫成className(因?yàn)楫吘故窃趯戭恓s代碼,會(huì)收到j(luò)s規(guī)則的現(xiàn)在,而class是關(guān)鍵字)
<p className="hello" style = {this.style}>Hello world</p>
· 不同的條件添加不同的樣式
有時(shí)候需要根據(jù)不同的條件添加不同的樣式,比如:完成狀態(tài),完成是綠色,未完成是紅色。那么這種情況下,我們推薦使用classnames這個(gè)包:
· css-in-js
styled-components是針對(duì)React寫的一套css-in-js框架,簡(jiǎn)單來(lái)講就是在js中寫css。npm鏈接
組件化開發(fā)React todolist, 項(xiàng)目開發(fā)中的組件的基本目錄結(jié)構(gòu)基本上是這樣的:
注意:一個(gè)組件只干一件事情 ,所以TodoList和TodoItem要做成兩個(gè)組件,這樣也方便于后期理解shouldComponentUpdate
關(guān)于“React的相關(guān)知識(shí)點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。