天天看點

React

React是用于建構使用者的JS庫(Facebook開源)

使用JS進行操作DOM會進行大量的重繪重排列

React采用元件化模式、聲明式編碼提高開發效率及元件複用率

React使用虛拟DOM和Diffing算法,減少與真實DOM的互動

Diffing算法:當浏覽器進行更新時會和舊虛拟Dom進行比對,當比對到相同的虛拟Dom時不進行更新,隻更新比對不到(新的)的虛拟Dom

Recact使用jsx文法聲明元素

基本的React使用(後期可用React腳手架進行項目搭建,無需引入這些樣式和聲明)

建立一個容器,并引入react相關庫檔案<div id="test"></div><!-- 引入react核心庫 --><script src="./js/react.development.js"></script><!-- 引入react-dom操作dom --><script src="./js/react-dom.development.js"></script><!-- 引入babel,将jsx轉換為js --><script src="./js/babel.min.js"></script>

聲明一個script标簽并使用jsx文法建立虛拟DOM

虛拟dom本質是一個object對象(一般對象)

虛拟DOM比較“輕”,真實dom比較“重”,因為虛拟dom是react内部在使用,無需真實DOM那麼多屬性,但虛拟DOM會被React使用Diffing算法轉換為真實DOM

全稱JavaScript XML,本質上React的文法糖React.createElement(component, props, ...children),主要是用來簡化建立虛拟DOM

可以使用大括号引入js表達式(js語句和js表達式不同,一個表達式會産生一個值,可以使用變量接收到,比如a,a+b,function,一個語句則是控制代碼走向的,如if、for、swich)

如果需要指定樣式要使用className

如果要使用内聯樣式要使用style={{key:value}}

隻要用了JSX,都要加上type="text/babel", 聲明需要babel來處理

1.使用函數聲明一個元件并使用标簽渲染到頁面上

function Demo() {

}

ReactDOM.render(<Demo/>,document.getElementById('test'))

類中的構造器不是必須寫的,要對執行個體進行一些初始化的操作,比如添加需要指定屬性時

如果A類繼承了B類,且A類中寫了構造器,那麼A類中的super必須要調用

類中的所有方法都是放在原型對象上的,供執行個體使用

// 建立類式元件

簡單元件和複雜元件

有狀态的元件為複雜元件,用類定義,沒有狀态的為簡單元件,用函數定義

通過更新元件的狀态來更新頁面

在類式元件中,可以在constructor函數中聲明使用鍵值對聲明state

constructor(props) {

注意:state的狀态不能直接更改,需要借助API-setState修改

元件中的自定義方法 this指向undefined,如何解決?

a) 強制綁定this: 通過函數對象的bind()

b) 箭頭函數,即指派語句,不能直接用箭頭函數

props主要通過标簽屬性從元件外向元件内傳遞資料

props是隻讀的,不能直接修改

使用擴充運算符...

多用于數組,在react中也可以用于展開對象,要放在标簽内

使用propTypes可以對屬性進行規則限制

函數式元件也能使用props,通過參數傳遞,如果需要參數限制将上方寫在類中的static寫到外面,使用Person定義

props(“properties” 的縮寫)和 state 都是普通的 JavaScript 對象。它們都是用來儲存資訊的,這些資訊可以控制元件的渲染輸出,而它們的一個重要的不同點就是:props 是傳遞給元件的(類似于函數的形參),而 state 是在元件内被元件自己管理的(類似于在一個函數内聲明的變量)。

字元串形式的ref

元件内的标簽可以通過ref進行辨別,相當于原生js的id

<input ref="input1"/>

回調函數式的ref

<input ref={(currentNode)=>{this.input1=currentNode}}/>

回調函數式的ref可以簡寫

<input ref={c=>this.input1=c}/>

此ref會被直接挂載this上,直接在this中解構指派即可

createRef API 建立ref容器

myRef= React.createRef()

<input ref={this.myRef}/>

不要過度使用ref,如果發生事件的元素是觸發事件的元素,即可以使用event.target操作元素

比如是失去焦點擷取輸入框的值,通過event.target可以得到發生事件的DOM元素對象

高階函數擁有以下兩個特性之一

1.A函數接收的參數是一個函數

2.A函數的傳回值還是一個函數

常見的高階函數有:Promise、setTimeout、arr.map()等

函數的柯裡化:通過函數繼續調用傳回函數,實作多次傳參并統一處理

元件被挂載上去會自動調用函數componentDidMount,通常用來開啟定時器、發送ajax請求,訂閱消息等

元件将解除安裝之前會自動調用函數componentWillUnmount,通常用來來關閉定時器、取消訂閱

元件初始化會自動調用函數render,每次更新都會調用

初始化階段由ReactDOM.render()觸發---初次渲染

constructor()

componentWillMount()

render()

componentDidMount()

更新階段由元件内部this.setSate()或父元件重新render觸發

shouldComponentUpdate()

componentWillUpdate()

componentDidUpdate()

解除安裝元件 由ReactDOM.unmountComponentAtNode()觸發

componentWillUnmount()

初始化階段: 由ReactDOM.render()觸發---初次渲染

1.constructor()

2.getDerivedStateFromProps

3.render()

4.componentDidMount()

更新階段: 由元件内部this.setSate()或父元件重新render觸發

1.getDerivedStateFromProps

2.shouldComponentUpdate()

4.getSnapshotBeforeUpdate

5.componentDidUpdate()

解除安裝元件: 由ReactDOM.unmountComponentAtNode()觸發

1.componentWillUnmount()

即将廢棄的鈎子

1.componentWillMount

2.componentWillReceiveProps

3.componentWillUpdate

虛拟DOM中key的作用

1) .簡單的說:key是虛拟DOM對象的辨別,在更新顯示時key起着極其重要的作用。

2) .詳細的說:當狀态中的資料發生變化時,react會根據【新資料】生成【新的虛拟DOM】,

随後React進行【新虛拟DOM】與【舊虛拟DOM】的diff比較,比較規則如下

a. 舊虛拟DOM中找到與新虛拟DOM相同的key:

(1) .若虛拟DOM中内容沒變,直接使用之前的真實DOM

(2) .若虛拟DOM中内容變了,則生成新的真實DOM,随後替換掉頁面中之前的真實DOM

b. 舊虛拟DOM中未找到與新虛拟DOM相同的key

根據資料建立新的真實DOM,随後渲染到到頁面

2.用ndex作為key可能會引發的問題:

1.若對資料進行:逆力添加、逆序删除等破壞順序操作:

會産生沒有必要的真實DOM更新==> 界而效果沒問題,但效率低。

2 .如果結構中還包含輸入類的DOM:

會産生錯誤DOM更新==> 界面有問題。

3 .注意:如果不存在對資料的逆序添加、逆序删除等破壞順序操作,

僅用于演染清單用f展示,使用index作為key是沒有問題的。

3.開發中如何選擇key?

1 .最好使用每條資料的唯一辨別作為key,比如id、手機号、身份證号、學号等唯一值。

2 .如果确定隻是簡單的展示資料,用index也是可以的。

腳手架是用來幫助程式員快速建立一個基于xxx庫的模闆項目

react提供了一個用于建立react項目的腳手架庫: create-react-app

使用腳手架開發的項目的特點: 子產品化, 元件化, 工程化

第一步,全局安裝:npm i -g create-react-app

第二步,切換到想創項目的目錄,使用指令:create-react-app hello-react

第三步,進入項目檔案夾:cd hello-react

第四步,啟動項目:npm start/yarn start

父元件<Father/>

子元件<Son />

在父元件中使用自定義方法,通過子元件使用props的方法的形參傳遞

元件擁有共同的狀态可以将狀态放在元件共有的父元件上

狀态在哪裡,操作狀态的方法就在哪裡

使用消息訂閱

插件庫:PubSubJS

下載下傳: npm install pubsub-js --save

使用:

import PubSub from 'pubsub-js' //引入

PubSub.subscribe('delete', function(mag,data){ }); //訂閱,必須傳兩個參數,在元件挂載完畢即componentDidMount

PubSub.publish('delete', data) //釋出消息

如果不需要消息需要取消訂閱和取消定時器一樣,在元件解除安裝時調用

PubSub.unsubscribe(this.消息名)

ajax跨域代理

在package.json中追加如下配置

說明:

優點:配置簡單,前端請求資源時可以不加任何字首。

缺點:不能配置多個代理。

工作方式:上述方式配置代理,當請求了3000不存在的資源時,那麼該請求會轉發給5000 (優先比對前端資源)

第一步:建立代理配置檔案

編寫setupProxy.js配置具體代理規則:

優點:可以配置多個代理,可以靈活的控制請求是否走代理。

缺點:配置繁瑣,前端請求資源時必須加字首。

‘jquery和axios都是基于xhr(XMLHttpRequest)發送ajax請求

fetch: 原生函數,不再使用XmlHttpRequest對象送出ajax請求

注意:老版本浏覽器可能不支援

Get請求:

Post請求

一個路由就是一個映射關系(key:value)

key為路徑, value可能是function(後端路由,目前端請求時傳回函數調用的結果)或component(前端路由)

1) 了解: value是function, 用來處理用戶端送出的請求。

2) 注冊路由: router.get(path, function(req, res))

3) 工作過程:當node接收到一個請求時, 根據請求路徑找到比對的路由, 調用路由中的函數來處理請求, 傳回響應資料

1) 浏覽器端路由,value是component,用于展示頁面内容。

2) 注冊路由: <Route path="/test" component={Test}>

3) 工作過程:當浏覽器的path變為/test時, 目前路由元件就會變為Test元件

插件庫:react-router-dom

導航區的a标簽改為Link标簽

<code>&lt;Link to="/home"&gt;Home&lt;/Link&gt;</code>

展示區的Route進行路徑與元件比對

<code>&lt;Route path='/home' component={Home}/&gt;</code>

在index的APP外包裹<code>&lt;BrowserRouter&gt;</code>或<code>&lt;HashRouter&gt;</code>

差別

1.底層原理不一樣:

BrowserRouter使用的是H5的history API,不相容IE9及以下版本。

HashRouter使用的是URL的哈希值。

2.path表現形式不一樣

BrowserRouter的路徑中沒有#,例如:localhost:3000/demo/test

HashRouter的路徑包含#,例如:localhost:3000/#/demo/test

3.重新整理後對路由state參數的影響

(1).BrowserRouter沒有任何影響,因為state儲存在history對象中。

(2).HashRouter重新整理後會導緻路由state參數的丢失!!!

4.備注:HashRouter可以用于解決一些路徑錯誤相關的問題。

NavLink是Link标簽的更新版,如果被點選時想添加屬性可以使用activeClassName="屬性名"

<code>&lt;NavLink activeClassName="backColor" to="/about"&gt;About&lt;/NavLink&gt;</code>

對NavLink進行封裝,标簽體的内容會通過props屬性的children傳遞給子元件,是以可以直接結構指派出所有的props

Swich标簽可以進行單一比對,如果兩個路由的位址相同但元件不同,預設會展示兩個元件

使用swich可以避免展示兩個元件,比對到第一個就不繼續進行比對

一般寫在所有路由注冊的最下方,當所有路由都無法比對時,跳轉到Redirect指定的路由

在public的index.html中可能會引入外部樣式,因為路由的原因導緻樣式丢失

解決方法:

1.public/index.html 中 引入樣式時不寫 ./ 寫 / (常用)

2.public/index.html 中 引入樣式時不寫 ./ 寫 %PUBLIC_URL% (常用)

3.使用HashRouter代替BrowserRouter(少用)

路由的比對規則預設為模糊比對

開啟精準比對<code>&lt;Route exact={true} path="/about" component={About}/&gt;</code>

可以簡寫<code>&lt;Route exact path="/about" component={About}/&gt;</code>

注意:嚴格比對不要随便開啟,需要再開,有些時候開啟會導緻無法繼續比對二級路由

多級路由需要加上父路由的path值

1.params參數

路由連結(攜帶參數):&lt;Link to='/demo/test/tom/18'}&gt;詳情&lt;/Link&gt;

注冊路由(聲明接收):&lt;Route path="/demo/test/:name/:age" component={Test}/&gt;

接收參數:this.props.match.params

2.search參數

路由連結(攜帶參數):&lt;Link to='/demo/test?name=tom&amp;age=18'}&gt;詳情&lt;/Link&gt;

注冊路由(無需聲明,正常注冊即可):&lt;Route path="/demo/test" component={Test}/&gt;

接收參數:this.props.location.search

備注:擷取到的search是urlencoded編碼字元串,需要借助querystring的parse方法解析

3.state參數

路由連結(攜帶參數):&lt;Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}&gt;詳情&lt;/Link&gt;

接收參數:this.props.location.state

備注:重新整理也可以保留住參數

可以在不借助Link和NavLink的情況下進行導航的跳轉

借助this.prosp.history對象上的API對操作路由跳轉、前進、後退

this.prosp.history.push(要去往的路由)

this.prosp.history.replace(要取代的路由,不留下曆史記錄)

this.prosp.history.goBack()後退一步

this.prosp.history.goForward()前進一步

this.prosp.history.go(n)後退或前進n步,n為負值是後退

路由元件有自帶的三個props屬性,而如果是自己用标簽注冊的元件則沒有props屬性

history

location

match

如果一般元件也想使用路由元件的特有API可以使用withRouter

導入withRouter,并在導出元件時使用withRouter(元件名)方法導出,傳回一個新元件

安裝antd:yarn add antd

按需引入即可,記得引入樣式

樣式可以進行按需引入參考官方文檔即可

繼續閱讀