在jsx中不能使用class定義類名 由於class在js中是用來定義類的 定義類名的時候用className
label中的for必須寫成htmlFor
ReactDOM.render:
參數1:須要渲染的dom元素或者組件
參數2:須要將渲染好的元素掛載在哪一個掛載點身上
參數3:回調 成功的回調
React中如何建立一個組件
經過class類的方式來建立一個組件
class 組件名稱 extends React.Component
注意:這個組件中必需要寫一個render函數 函數中必須返回一個jsx語法
插槽做用:
插槽即:ReactDOM.createPortal(child, container) ,由ReactDom提供的接口。 能夠實現將子節點渲染到父組件DOM層次結構以外的DOM節點。
第一個參數(child)是任何可渲染的 React 子元素,例如一個元素,字符串或 片斷(fragment)。第二個參數(container)則是一個 DOM 元素。
應用場景:
對於 portal 的一個典型用例是當父組件有 overflow: hidden 或 z-index 樣式,但你須要子組件可以在視覺上 「跳出(break out)」 其容器。例如,對話框、hovercards以及提示框。因此通常react組件裏的模態框,就是這樣實現的~
React.Component:
是全部組件的父類。經過繼承父類來建立組件。這個類中會包含不少方法(例如生命週期)
render:
是一個生命週期,用來渲染jsx語法
constructor:
是一個生命週期函數,用來存放當前組件所須要的一些狀態 狀態存放在this.state中這個類中的this指向會指向當前這個組件
注意:當書寫了constructor後必需要寫super不然this的指向會發生錯誤
React中的事件綁定優化
一、不須要傳值的狀況下去
在constructor中定義函數 例如:this.handleClick = this.handleClick.bind(this)
在render函數中使用定義好的函數 <button onClick={this.handleClick}>點擊</button>
二、須要傳值的狀況下
<button onClick={this.handleClick.bind(this,須要傳遞的值)}>點擊</button>
三、不推薦使用
<button onClick={()=>{
this.setState({
message:123
})
}}>點擊</button>
setState:
當須要修改this.state中的數據的時候咱們須要調用this.setState;
this.setState這個方法是異步的
書寫方式2種
一、
this.setState({
key:val
})
二、this.setState((state)=>{
let str = (state.message + "").split("").reverse().join("")
return {
message:str
}
})
參數1:是一個對象 || 是一個函數 這個函數必須返回一個對象
參數2:回調 做用:一、驗證數據是否修改爲功 二、獲取數據更新後最新的DOM結構
setState 只在合成事件和鉤子函數中是「異步」的,在原生事件和 setTimeout 中都是同步的。
setState的「異步」並非說內部由異步代碼實現,其實自己執行的過程和代碼都是同步的,只是合成事件和鉤子函數的調用順序在更新以前,致使在合成事件和鉤子函數中無法立馬拿到更新後的值,形式了所謂的「異步」,固然能夠經過第二個參數 setState(partialState, callback) 中的callback拿到更新後的結果。
setState 的批量更新優化也是創建在「異步」(合成事件、鉤子函數)之上的,在原生事件和setTimeout 中不會批量更新,在「異步」中若是對同一個值進行屢次 setState , setState 的批量更新策略會對其進行覆蓋,取最後一次的執行,若是是同時 setState 多個不一樣的值,在更新時會對其進行合併批量更新。
react生命週期
constructor():(1次)
進行組件的初始化,且必需要寫super函數,不然this指向會發生錯誤
能夠用this.state來定義當前組件所須要的一些狀態
當前生命週期特殊狀況下接收不到props 的數據,若是想要接收到數據,須要在super和 constructor中傳遞props這個參數
componentWillMount():(1次) 掛載前 (17.0版本廢除了)
當前生命週期能夠接收到props傳遞過來的數據,能夠將外部數據轉化爲內部數據
注意儘可能不要使用this.state 由於當前生命週期執行完畢之後,下一個生命週期就是render函數 在當前生命週期中咱們能夠對this.state中的數據作初始化的最後一次修改
render():(屢次) 渲染
做用是將數據與虛擬DOM進行結合,進行數據渲染,而且在第一次執行完會將渲染結果在內存中保留一份
第二次執行的時候會與內存中的虛擬DOM進行對比 這種方式叫作diff算法(新舊兩個虛擬DOM的對比就是diff算法)
key值的做用:
componentDidMount():掛載後(1次)
當前生命週期能夠獲取到真實的DOM結構,通常狀況下咱們能夠在當前生命週期中進行Ajax的請求||進行方法的實例化
如何獲取到真實的dom結構
一、this.refs 屬性
二、<元素 ref={(形參)=>this.屬性 = 形參}></元素>
這裏面的形參表明的是當前的DOM元素 使用: this.屬性
componentWillReceiveProps():(屢次) (廢除)
當props的數據發生改變的時候當前生命週期就會執行,當前是生命週期中有一個參數就是新的props
在當前生命週期中能夠用來檢測外部數據的更新
shouldComponentUpdate()(屢次)
一、當state||props中的數據發生改變的時候會執行當前生命週期,當前生命週期必需要返回一個布爾值, 當返回true的時候會執行
下面的生命週期,若是返回false則下面的生命週期不會執行(render函數不會執行),
二、當前生命週期中會有2(3)個參數 一個是新的props 一個是新的state。咱們能夠經過新的props ||state 與 舊的props和state進行
對比,來進行性能優化
三、當前生命週期決定的是render函數是否渲染,而不是數據是否更新,哪怕返回值是false 數據其實也會進行更新的
四、千萬不要在這裏面執行this.setState不然會形成死循環
componentWillUpdate:(屢次) (廢除)
當前生命週期能夠用來作更新數據的最後一次修改
當前生命週期中有2個參數一個是新的props 一個是新的state 咱們能夠經過新的props || 新的state來作數據最後的一次更改
componentDidUpdate():(屢次)
當前生命週期能夠獲取到數據更新後最新的DOM結構
當前生命週期數據與模板已經進行相結合,生成最新的DOM結構了
注意若是咱們在當前生命週期中作一些實例化的時候 必定要加判斷
當前生命週期也有2個參數 一個是舊的props 一個是舊的state
componentWillUnmont():卸載(一次)
當前生命週期的做用來作事件的解綁 / 事件移除 等操做
面試題
面試題
一、組件加載的時候第一次執行的生命週期有哪些?
constructor
componentWillMount
render
componentDidMount
二、哪些生命週期會執行一次?
constructor
componentWillMount
componentDidMount
componentWillUnmount
三、哪些生命週期會執行屢次
render
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
四、當this.setState執行完畢之後會執行哪些生命週期
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
五、當this.props發生改變的時候會執行哪些生命週期
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
六、當組件的key值發生改變的時候會執行哪些生命週期
componentWillUnmount
constructor
componentWillMount
render
componentDidMount
context 跨組件傳值
一、經過react.createContext建立全局的GlobalContext來建立 一個 context
二、在根組件中經過GlobalContext.Provider建立一個全局的生產者
三、GlobalContext.provide中有一個屬性value用來定義子組件所須要用到的狀態值
四、在子組件中經過GlobalContext.Consumer來建立消費者。GlobalContext.Consumer內部必須經過一個函數來接收生產者的狀態,且這個函數必須返回一個jsx語法。
路由
一、安裝路由 cnpm install react-router-dom -S
二、引入react-router-dom 選擇引入形式
一、 HashRouter : 路由的根組件 也是路由的一種形式 (hash路由) 帶#號
全部的路由的配置下項都必須在路由的根組件內部
二、BrowerRouter : 路由的根組件 也是路由的一種 (history路由) 不帶#號
三、引入Router Router 是路由渲染的方式
經常使用的屬性:
path:路徑
component:須要渲染的組件 值是組件的名稱
render: 須要渲染的組件 值是組件
exact:徹底匹配
四、路由跳轉的方式 a標籤 link NavLink 編程式導航
Link && NavLink區別?
前者沒有選中的標識 後者會有選中的標識
場景:前者非TabBar 後者TabBar
屬性:
activeClassName: 設置選中後的類名
activeStyle:設置選中後的狀態
五、Redirect:路由重定向
屬性:
from:從哪裏來
to:到哪裏去
exact:徹底匹配
最外層加上Switch
六、Switch
Switch 是一個組件 做用是隻匹配一個路由
七、路由的嵌套
一、經過render的方式進行嵌套
二、將嵌套的內容放到Switch的外面
八、路由的傳參
動態路由:(使用最多)
一、在定義路由的時候/:屬性的方式來定義傳遞的屬性
二、在路由跳轉的時候傳遞須要傳遞的數據
三、接收:this.props.match.params
Query傳值:
一、在路由跳轉的時候經過地址拼接的方式進行數據的傳遞(相似於get傳值的方式)
二、接收的時候經過this.props.loacltion.search 進行接收(注意須要url模塊的解析)
const url = require("url");
對象傳值:
一、在路由跳轉的時候經過對象的方式進行路由跳轉
<li key={index}><Link to={{pathname:"/detail",query:{id:item.id,name:item.name}}}>{item.name}</Link></li>
二、二、接收的時候經過this.props.location.query進行接收
(注意:刷新瀏覽器的時候數據會丟失 慎用)
九、編程式導航:
this.props.history.goBack()
this.props.history.push()
this.props.history.goForward()
this.props.history.replace()
例如:
this.props.history.push({pathname:"/detail",query:{id:item.id,name:item.nam}})
render 與 component 的區別?
render:
一、render能夠渲染組件,以及標籤
二、render渲染方式能夠進行組件傳參
三、render的渲染方式能夠進行邏輯判斷
四、render的渲染方式能夠進行路由嵌套
component:
一、只能渲染組件,由於component的值是組件的名稱,而不是組件標籤
二、component的值由於組建的名稱不能傳遞,也不能作邏輯判斷 以及路由嵌套
三、只要經過component渲染的組件,身上會有三個屬性 history location match (優勢)
函數組件與類組件的區別?
函數組件:
優勢: 運行速度快 沒有狀態 也沒有生命週期 只會有view層 相似於UI組件
類組件:
優勢:能夠存儲組件所須要的狀態 以及繼承過來的一些生命週期的調用
Hooks:
讓函數組件擁有類組件的一些功能(存儲狀態 生命週期)
useState : 函數 書寫多個的
存儲當前組件所須要的一些狀態
參數:所須要的狀態值
返回值:數組
一、當前狀態的key值
二、修改當前狀態的函數
hooks中的生命週期 : componentDidMount componentDidUpdate componentWillUnmount (模擬出來的)
useEffect:模擬類組件的一些生命週期
參數1:函數
參數2:依賴值
若是第二個參數不寫的狀況下,參數1能夠模擬 componentDidMount componentDidUpdate
若是第二個參數書寫的狀況下,且第二個參數是一個不變值得狀況下 第一個參數只能模擬 componentDidMount
若是須要模擬componentWillUnmount 則只須要第一個參數中return 一個函數 在這個函數中作一些卸載組件的操做(事件的移除 解綁等)
flux: 公共狀態管理
安裝:cnpm install flux -S
一、View
二、Action
三、Dispatcher
四、Store
流程:
一、用戶訪問 View
二、View 發出用戶的 Action
三、Dispatcher 收到 Action,要求 Store 進行相應的更新
四、Store 更新後,發出一個"change"事件
五、View 收到"change"事件後,更新頁面
缺點:
一、管理多個store
二、頻繁引入store
三、UI組件 容器組件的拆分
四、事件訂閱每次都須要綁定
redux :公共狀態管理
安裝 cnpm install redux -S
數據傳遞的流程:
當組件須要修改數據的時候必須建立一個action,而後經過store.dispatch將action傳遞給store,store接收到action後將action傳遞給reducer,reducer接收到action後將action.type相比較,而後進行數據的修改,(要注意state只容許讀不容許修改,深拷貝)數據修改完後返回一個新的state。最後經過store.subscribe通知全部組件數據更新。
深拷貝的問題:
const newState = JSON.parse(JSON.stringify(state));
會深度拷貝每個節點 這個過程是特別耗費性能的
持久化數據結構 immutable 一旦被建立就不會再被更改的數據
原理:結構共享
特色:只要數據被修改就會返回一個新的immutable對象
fetch:
fetch是 window下面的一個方法,脫離了XHR 是ES的規範 兼容性不太好 fetch基於promise的API
一、安裝
cnpm install whatwg-fetch -S
二、GET請求 默認就是get請求
fetch(url+?key=val,{
headers:請求頭
method:請求的方式
})
三、post
fetch(url,{
headers:請求頭
method:請求的方式
body:post傳遞參數的屬性
})
特色:
無論post請求仍是get請求,當請求成功後第一個.then中是一個未處理的結果集
第二個.then中才是你想要的數據。fetch默認是不會攜帶cookie的,若是須要攜帶cookie則設置
credentials:"include"
fetch(url)
.then((res)=>{結果集的處理})
.then((data)=>{
console.log(data);
})
結果集的處理:你想要的數據格式是哪一種格式 text json blob formData
二、GET請求 默認即便get請求
fetch(url+?key=val,{
headers:請求頭,
method:請求方式
})
三、POST請求
fetch(url,{
headers:請求頭,
method:請求方式
body:post傳遞參數的屬性
})
特色:不管是post仍是get請求,當請求成功後的第一個.then中的是一個未處理的結果集
第二個.then中才是你想要的數據。fetch默認不會攜帶cookie
axios 是一個基於Promise 用於瀏覽器和 nodejs 的 HTTP 客戶端,它自己具備如下特徵:
從瀏覽器中建立 XMLHttpRequest
從 node.js 發出 http 請求
支持 Promise API
攔截請求和響應
轉換請求和響應數據
自動轉換JSON數據
客戶端支持防止CSRF/XSRF
fetch:
符合關注分離,沒有將輸入、輸出和用事件來跟蹤的狀態混雜在一個對象裏
更加底層,提供的API豐富(request, response)
脫離了XHR,是ES規範裏新的實現方式
1)fetchtch只對網絡請求報錯,對400,500都當作成功的請求,須要封裝去處理
2)fetch默認不會帶cookie,須要添加配置項
3)fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現的超時控制並不能阻止請求過程繼續在後臺運行,形成了量的浪費
4)fetch沒有辦法原生監測請求的進度,而XHR能夠
purComponent:
一、 pureComponent表示一個純組件,能夠用來優化react程序。減小render函數渲染的次數。提升性能
pureComponent進行的是淺比較,也就是說若是是引用數據類型的數據,只會比較不是同一個地址,而不會比較這個地址裏面的數據是否一致
淺比較會忽略屬性和或狀態突變狀況,其實也就是數據引用指針沒有變化,而數據發生改變的時候render是不會執行的。若是咱們須要從新渲染那麼就須要從新開闢空間引用數據
好處:
當組件更新時,若是組件的props或者state都沒有改變,render函數就不會觸發。省去虛擬DOM的生成和對比過程,達到提高性能的目的。具體緣由是由於react自動幫咱們作了一層淺比較
二、使用場景
一、PureComponent通常會用在一些純展現組件上。切結props和state不能使用同一個引用
二、在經過PureComponent進行組件的建立的時候不可以在寫shouldComponentUpdate. 不然會引起警告
腳手架 cnpm install create-react-app -g
create-react-app react-demo 後面是文件名
Immutable
實現的原理是 Persistent Data Structure(持久化數據結構),也就是使用舊數據建立新數據時,要保證舊數據同時可用且不變。同時爲了不 deepCopy 把全部節點都複製一遍帶來的性能損耗,Immutable 使用了 Structural Sharing(結構共享),即若是對象樹中一個節點發生變化,只修改這個節點和受它影響的父節點,其它節點則進行共享。 Immutable 則提供了簡潔高效的判斷數據是否變化的方法,只需 === 和 is 比較就能知道是否須要執行 render(),而這個操做幾乎 0 成本,因此能夠極大提升性能。
1、immutable簡介
Immutable Data 就是一旦建立,就不能再被更改的數據。對 Immutable 對象的任何修改或添加刪除操做都會返回一個新的 Immutable 對象。Immutable 實現的原理是 Persistent Data Structure(持久化數據結構),也就是使用舊數據建立新數據時,要保證舊數據同時可用且不變。同時爲了不 deepCopy 把全部節點都複製一遍帶來的性能損耗。
在js中,引用類型的數據,優勢在於頻繁的操做數據都是在原對象的基礎上修改,不會建立新對象,從而能夠有效的利用內存,不會浪費內存,這種特性稱爲mutable(可變),但偏偏它的優勢也是它的缺點,太過於靈活多變在複雜數據的場景下也形成了它的不可控性,假設一個對象在多處用到,在某一處不當心修改了數據,其餘地方很難預見到數據是如何改變的,針對這種問題的解決方法,通常就像剛纔的例子,會想複製一個新對象,再在新對象上作修改,這無疑會形成更多的性能問題以及內存浪費。
爲了解決這種問題,出現了immutable對象,每次修改immutable對象都會建立一個新的不可變對象,而老的對象不會改變
2、React中如何減小render函數渲染的次數
在React中咱們知道當this.state 、this.props發生改變的時候render函數就會執行,但有些時候this.state、this.props沒有發生改變的時候render函數也會執行(具體請自行了解相關案例,如需詳解請留言)。那麼咱們如何來減小render函數渲染的次數來提升React的性能優化?接下來咱們能夠封裝一個BaseComponent來減小React中render函數渲染的次數
i
注意:本文所進行優化的數據必須統一都是immutable數據,哪怕是this.props
00一、react中如何建立一個組件
方案一:ES6寫法
class
組件名稱
extends
Component
{ }
方案二:ES5寫法
var App = React.createClass({})
00二、render函數何時會執行?
當
this.state 或者this.props發生改變的時候render函數就會執行
00三、react中如何對state中的數據進行修改?setState爲何是一個異步的
修改數據經過this.setState(參數
1,參數2)this.setState是一個異步函數
參數1: 是須要修改的數據是一個對象,
參數2: 是一個回調函數,能夠用來驗證數據是否修改爲功,同時能夠獲取到數據更新後的DOM結構 等同於componentDidMount
this.setState中的第一個參數除了能夠寫成一個對象之外,還能夠寫成一個函數,函數中第一個值爲prevState 第二個值爲prePprops
this.setState((prevState,prop)=>({}))
爲何setState是一個異步的?當批量執行state的時候可讓DOM渲染的更快,也就是說多個setstate在執行的過程當中還須要被合併
00四、react中如何定義自定義屬性,以及限制外部數據的類型
一、自定義屬性
組件名稱.defaultProps={
key:val
}
二、限制外部數據的類型
a、引入propTypes第三方模塊
b、類型限制
組件名稱.propTypes={
key:propTypes.類型
}
00五、react路由經常使用的一些組件配置項有哪些?
BrowserRouter
HashRouter
withRouter
Route
Link
NavLink
Switch
Redirect
BrowserRouter 和 HashRouter是路由的根組件,跟組件下面只能有一個子元素
Route是路由路徑所對應的組件
Link和 NavLink是進行路由的跳轉。區別是當選中標籤的時候NavLink會加上一個class
Swicth:被Switch包裹的Route渲染的時候只會渲染一個路徑,建意:子頁面不要放在Switch裏面,主頁面放在Switch裏面
Redirect:設置路由的重定向
00六、reatc路由中Route渲染組件的方法有哪幾種?區別是什麼?
渲染方式有2種
一、<Route path="/home"component={組件名稱}></Route>
經過component進行組件的渲染,這種方式的優勢在於能夠直接在組件的內部接受到history、location、match,缺點在於若是須要組件傳參,或者渲染jsx語法的時候沒法使用
二、<Route path="/home" render={()=>{return<Home/>}}>
</Route>
經過render進行渲染組件,優勢在於能夠進行組件傳參,還能夠渲染非組件的標籤,缺點在於若是須要使用 histroy location match的話須要在函數中傳遞過去
00七、如何控制路由的路徑徹底匹配
給NavLink 或者 Route設置 exact屬性
00八、react中路由傳遞參數的方法有哪些?
方案一:
//經過params進行傳值
<Router path="/one/:id"
render={(history)=>{
return <One history={history}/>
}}>
// html跳轉:
<NavLikn to={"/one/"+1}>one<NavLink>
// js跳轉:
this.props.history.push('/one/'+'1')
// 接收值:
在組件內部經過
constructor
參數進行接受
constructor({history,location,match}){
super();
/進行接受
console.log(
match.params)}
// 方案二:
// 經過query
<Router path="/one" render={(history)=>{
return <One history={history}/>
}}>
// html跳轉:
<NavLikn to={{
pathname:"/one",
query:{data:1}}}>one<NavLink>
// js跳轉:
this.props.history.push({ pathname :
'/one',query : { data:1} })
// 獲取值
this.props.location.query.data
注意:若是經過render進行渲染的時候須要在回調中將history的值傳遞過去.若是是component進行渲染的話,咱們只須要經過
this.props進行接受便可。
00九、react中的編程式導航方法有哪些?
this.props.history.push("須要跳轉的路徑");跳轉路徑
this.props.history.back();返回
this.props.history.forward():前進
this.props.history.replace():替換
0十、react中的生命週期有哪些?
(1)、組件建立的過程
constructor
componentWillMount
render
componentDidMount
(2)當props中的數據發生改變後會執行哪些生命週期函數
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
(3)組件銷燬的時候
componentWillUnmount
0十一、reatc中如何強制更新DOM
this.foreUpdate()
0十二、談談你對react生命週期中shouldComponentUpdate的理解
shouldComponentUpdate是react性能優化很是重要的一環。
組件接受新的
state或者props時調用,咱們能夠設置在此對比先後兩個props和state是否相同,若是相同則返回false阻止更新,由於相同的屬性狀態必定會生成相同的dom樹,這樣就不須要創造新的dom樹和舊dom樹進行diff算法對比,節省大量性能,尤爲是在dom結構複雜的時候
01三、談談你對虛擬DOM的理解,以及好處?
虛擬DOM:虛擬DOM其實就是真實的js對象虛擬DOM提升了react的性能,每次數據更新後都會從新計算上虛擬DOM,並和上一次的虛擬DOM進行對比,對方法變化的部分進行批量更新。react中也提供了
shouldComponentUpdate生命週期的回調,來減小數據變化後沒必要要的虛擬DOM對比過程。保證性能
01四、談談你對flux的理解
利用單項數據流的方式來組合react的視圖組件,它是一種模式,而不是一種框架
簡單來講flux能夠幫咱們解決非父子組件之間傳值
flux數據傳遞流程
https://www.cnblogs.com/nanianqiming/p/9870194.html
01五、react17廢除的生命週期函數,與新增的生命週期函數
因爲將來採用異步渲染機制,因此即將在
17版本中去掉的生命週期鉤子函數
componentWillMount
componentWillRecieveProps
componentWIllUpdate
新增的生命週期
staticgetDerivedStateFromProps(nextProps, prevState){}用於替換componentWillReceiveProps,能夠用來控制 props 更新 state的過程;它返回一個對象表示新的 state;若是不須要更新,返回null便可在每次渲染以前都會調用,無論初始掛載仍是後面的更新都會調用,這一點 和componentWillReceiveProps不一樣(只有當父組件形成從新渲染時才調用) 每次都應該返回一個對象做爲
getSnapshotBeforeUpdate() {}
用於替換 componentWillUpdate,該函數會在update後 DOM 更新前被調用,
用於讀取最新的 DOM 數據,返回值將做爲 componentDidUpdate 的第三個參
數,在最新的渲染數據提交給DOM前會當即調用,它讓你在組件的數據可能要改
變以前獲取他們
componendDidCatch(error, info){}
若是一個組件定義了componentDidCatch生命週期,則他將成爲一個錯誤邊
界(錯誤邊界會捕捉渲染期間、在生命週期方法中和在它們之下整棵樹的構造
函數中的錯誤,就像使用了trycatch,不會將錯誤直接拋出了,保證應用的
可用性)
01六、this.setState以後react作了哪些操做
一、shouldComponentUpdate
二、componentWillUpdate
三、render
四、componentDidUpdate
01七、當組件的key值發生改變後會執行哪些生命週期函數?
1、componentWillUnmount
2、constructor
三、componentWillMount
四、render
5、componentDidMount
01八、在react中是否封裝過組件?封裝組件須要注意的地方?
經常使用封裝組件用到的東西
一、propTypes 限制外部數據的類型
二、defaultProps 設置默認的外部數據
三、父傳子 子傳父 context 等傳值方式
四、高階組件
封裝組件的時候必定要注意組件的複用性,靈活性
01九、如何接收組件內部的標籤/內容
經過
this.props.children
020、請說下你對redux的理解,以及使用的方式
其實redux就是Flux的一種進階實現。它是一個應用數據流框架,
主要做用應用狀態的管理
redux的三大原則
1、單一的數據源
2、state是隻讀的
3、使用純函數來進行修改redux中有
3個經常使用的方法
1、createStore() 建立store
2、combineReducers() 合併多個reducer
3、applyMiddleware() 使用中間件,處理異步的action
redux數據傳遞的流程
當組件須要改變Store數據的時候。須要建立一個Action,而後經過dispatch(action) 傳遞給Store,而後Store把Action轉發給Reducers.Reducers會拿到previousState(之前的state
數據) 和action。而後將previousState和action進行結合作新的數據(store)修改。而後生成一個新的數據傳遞給Store 。Store經過觸發subscribe()這個方法來調用函數執行setState使得view的視圖發生改變
00一、請說下在react中如何處理異步的action
經過applyMiddleware來使用中間件來處理action
經常使用的中間件
redux-promise-middleware
redux-thunk
redux-saga
00二、請說下redux中中間件的理解
中間件:請求和回覆之間的一個應用。
在redux中中間件是dispatch與reducer之間的一個應用
00三、請說下redux中你對reducers的理解,以及如何合併多個reducers
在redux中reducer是一個純函數,其中這個純函數會接收
2個參數一個是state一個是action。state用來保存公共的狀態,state有一個特色就是隻容許讀不容許進行修改 。在實際開發中由於會涉及到多人協做開發因此每一個模塊都會有一個reducer。
咱們能夠經過combineReducers來合併多個reducers
00四、請說下你對高階組件的理解,以及做用高階組件就是接受一個組件做爲參數,返回一個相對加強性的組件的函數高階組件是一個函數 並非組件
做用:
一、屬性代理
---主要進行組件的複用
二、反向集成
---主要進行渲染的劫持
00五、在react中如何解決單頁面開發首次加載白屏現象
一、經過路由懶加載的方式 react-loadable
二、首屏服務端渲染
00六、請說下react中key值的理解
react利用key來識別組件,它是一種身份標識標識,相同的key react認爲是同
一個組件,這樣後續相同的key對應組件都不會被建立
有了key屬性後,就能夠與組件創建了一種對應關係,react根據key來決定是銷燬
從新建立組件仍是更新組件。
key相同,若組件屬性有所變化,則react只更新組件對應的屬性;沒有變化則不
更新。
key值不一樣,則react先銷燬該組件(有狀態組件的componentWillUnmount會執行)
,而後從新建立該組件(有狀態組件的constructor和componentWillUnmount都會執行)
00七、組件第一次執行的時候會執行哪些生命週期函數
constructor
componentWillMount
render
componentDidMount
00八、哪些生命週期會執行屢次
render
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
00九、當this.state 或者this.props發生改變的時候會執行哪些生命週期函數
this.state
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
this.props
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
0十、談談你對context的理解
當你不想在組件樹中經過逐層傳遞props或者state的方式來傳遞數據時,可使用
Context來實現跨層級的組件數據傳遞,使用context能夠實現跨組件傳遞
舊版context的基本使用
一、getChildContext根組件中聲明,一個函數,返回一個對象, 就是context
二、childContextTypes根組件中聲明,指定context的結構類型, 如不指定,會產生錯誤
三、contextTypes子孫組件中聲明,指定要接收的context的結構類型, 能夠只是context的一部分結構。contextTypes沒有定義,context將是 一個空對象。
四、this.context在子孫組件中經過此來獲取上下文
新版
context的基本使用
一、根組件引入GlobalContext,並使用GlobalContext.Provider(生產者)
二、組件引入GlobalContext並調用context,使用GlobalContext.Consumer
0十一、談談你對react中withRouter的理解默認狀況下必須是通過路由匹配渲染的組件在
this.props上擁有路由參數,才能使用編程式導航的寫法,withRouter是把不是經過路由切換過來的組件,將react-router 的 history、location、match 三個對象傳入props對象上
簡單的來講就是否是路由包裹的組件也可使用路由的一些方法
0十二、說如下你對puerComoponent的理解pureComponent表示一個純組件,能夠用來優化react程序。減小render函數渲染的次數。提升性能
pureComponent進行的是淺比較,也就是說若是是引用數據類型的數據,只會比較不是同一個地址,而不會比較這個地址裏面的數據是否一致
好處:當組件更新時,若是組件的props或者
state都沒有改變,render函數就不 會觸發。省去虛擬DOM的生成和對比過程,達到提高性能的目的。具體緣由是由於react自動幫咱們作了一層淺比較
01三、react請求接口數據是在componentDidMount 仍是componentWillMount週期好
若是你要獲取外部數據並加載到組件上,只能在組件"已經"掛載到真實的網頁上才能做這事情,其它狀況你是加載不到組件的。componentDidMount方法中的代碼,是在組件已經徹底掛載到網頁上纔會調用被執行,因此能夠保證數據的加載React異步渲染開啓的時候,componentWillMount 就可能被中途打斷,中斷以後渲染又要重作一遍,若是在componentWillMount 中作 AJAX 調用,代碼裏看到只有調用一次,可是實際上可能調用 N 屢次,這明顯不合適。相反,若把 AJAX 放在componentDidMount,由於 componentDidMount 在第二階段,因此絕對不會屢次重複調用,這纔是 AJAX 合適的位置
1、React中key值得做用
react中的key屬性,它是一個特殊的屬性,它是出現不是給開發者用的,而是給React本身使用,有了key屬性後,就能夠與組件創建了一種對應關係,簡單說,react利用key來識別組件,他是一種身份標識,就像每一個人有一個身份證來作辨識同樣。每一個key 對應一個組件,相同的key react認爲是同一個組件,這樣後續相同的key對應組件都不會被建立
key值相同
若是兩個元素是相同的key,且知足第一點元素類型相同, 若元素屬性有所變化,則React只更新組件對應的屬性,這種狀況下,性能開銷會相對較小
key值不一樣
在render函數執行的時候,新舊兩個虛擬DOM會進行對比,若是兩個元素有不一樣的key,那麼在先後兩次渲染中就會被認爲是不一樣的元素,這時候舊的那個元素會被unmount,新的元素會被mount
//更新前
render(){
return ( <List key = '1'/>);
}
//更新後
render(){
return (
<List key = '2'/>
);
}
2、例子
//tree1
<ul>
<li key='1'>1</li>
<li key='2'>2</li>
</ul>
//tree 2
<ul>
<li key='1'>1</li>
<li key='3'>3</li>
<li key='2'>2</li>
</ul>
若是沒有key值得狀況下,react並不會執行插入操做,他直接會移除原先的第二個子元素,而後再append進去剩下的子元素,而其實咱們這個操做只只須要一個insert操做就能完成。爲了解決這種問題,react須要咱們提供給一個key來幫助更新,減小性能開銷
若是有key值得狀況下,react就會經過key來發現tree2的第二個元素不是原先tree1的第二個元素,原先的第二個元素被挪到下面去了,所以在操做的時候就會直接指向insert操做,來減小dom操做的性能開銷
3、不推薦用屬性中的index來作key值
大部分狀況下咱們要在執行數組遍歷的時候會用index來表示元素的key。這樣作其實並非很合理。咱們用key的真實目的是爲了標識在先後兩次渲染中元素的對應關係,防止發生沒必要要的更新操做。那麼若是咱們用index來標識key,數組在執行插入、排序等操做以後,原先的index並再也不對應到原先的值,那麼這個key就失去了自己的意義,而且會帶來其餘問題
4、注意事項
React中的key 值必須保證其惟一和穩定性
下面案例中key的值以Math.random() 隨機生成而定,這使得數組元素中的每項都從新銷燬而後從新建立,有必定的性能開銷
{
dataList.map((item,index)=>{
return <div style={mystyle} key={Math.random()}>{item.name}</div>
})
}
1、react-hooks概念
React中一切皆爲組件,React中組件分爲類組件和函數組件,在React中若是須要記錄一個組件的狀態的時候,那麼這個組件必須是類組件。那麼可否讓函數組件擁有類組件的功能?這個時候咱們就須要使用hooks。
Hooks讓咱們的函數組件擁有了相似類組件的特性,Hook是React16.8中新增的功能,它們容許您在不編寫類的狀況下使用狀態和其餘React功能
2、爲何React中須要類組件
一、須要記錄當前組件的狀態
二、須要使用組件的一些生命週期函數
兩者對比以後是否是感受Hooks簡單好多了?那麼接下來咱們來學習Hooks
4、Hooks基本使用
一、Hooks經常使用的方法
useState 、useEffect 、useContext以上三個是hooks常常會用到的一些方法
二、useState
useState是react自帶的一個hook函數,它的做用就是用來聲明狀態變量.useState這個函數接收的參數是咱們的狀態初始值,它返回了一個數組,這個數組的第 [0]項是當前的狀態值,第 [1]項是能夠改變狀態值的方法函數。
useState : 建立一個狀態,這個狀態爲0
count : 表明當前狀態值也就是0
setCount : 更新狀態的函數
addCount = ()=>setCount(count+1);調用setCount就能夠用來修改狀態
2-一、useState返回的是什麼?
const[count,setCount] = useState(0);
const state = useState(0);
const count = state[0];
const setCount = state[1]
注意:
一、useState必定要寫在函數初始的位置不能在循環或判斷語句等裏面調用,這樣是爲了讓咱們的 Hooks 在每次渲染的時候都會按照 相同的順序 調用,由於這裏有一個關鍵的問題,那就是 useState 須要依賴參照第一次渲染的調用順序來匹配對於的state,不然 useState 會沒法正確返回它對於的state
二、咱們能夠在一個函數組件中使用多個
export default()=>{
let[count,setCount] = useState(0);
let[count,setCount] = useState(0);
let[count,setCount] = useState(0);
}
5、useEffect基本使用
咱們寫的有狀態組件,一般會產生不少的反作用(side effect),好比發起ajax請求獲取數據,添加一些監聽的註冊和取消註冊,手動修改dom等等。咱們以前都把這些反作用的函數寫在生命週期函數鉤子裏,好比componentDidMount,componentDidUpdate和componentWillUnmount。而如今的useEffect就至關與這些聲明周期函數鉤子的集合體。它以一抵三。
(useEffect = componentDidMount+componentDidUpdate+componentWillUnmount)
5-一、useEffect
useEffect中有兩個參數,第一個參數是一個函數,第二個參數是一個依賴的數據。第二個參數用來決定是否執行裏面的操做,能夠避免一些沒必要要的性能損失,只要第二個參數中的成員的值沒有改變,就會跳過這次執行。若是傳入一個空數組 [ ],那麼該effect 只會在組件 mount 和 unmount 時期執行。
5-二、useEffect模擬componentDidMount && componentDidUpdate
importReact,{useState,useEffect}from"react"
export default()=>{
let[title,setTitle] = useState(0);
letupdateTitle =()=>setTitle(title+1);
return(
<div>
<h2>{title}</h2>
<button onClick={updateTitle}>點擊</button>
</div> )
//參數是一個函數 每次mount 或者 update都會調用當前函數
useEffect(()=>{
document.title =`頁面爲${count}`;
})
}
5-三、如何只在componentDidMount中執行
import React,{useState,useEffect} from"react" export default()=>{
let[title,setTitle] = useState(0);
let updateTitle =()=>setTitle(title+1);
return(
<div>
<h2>{title}</h2>
<buttononClick={updateTitle}>點擊</button>
</div>
)
//將第二個參數設置爲一個空數組則只會在componentDidMount中執行
useEffect(
()=>{document.title =`頁面爲${count}`; },[])}
5-二、useEffect模擬componentWillUnMount
useEffect 中還能夠經過讓函數返回一個函數來進行一些清理操做,好比取消訂閱等
useEffect =(()=>{
return()=>{
//unmount時調用這裏
document.removeEventListener();
}
},[])
4、useEffect 何時執行?
它會在組件 mount 和 unmount 以及每次從新渲染的時候都會執行,也就是會在 componentDidMount、componentDidUpdate、componentWillUnmount 這三個時期執行
5、hooks的好處
面向生命週期編程變成了面向業務邏輯編程
6、fetch與axios的區別
axios("http://xxx/xxx.json?a=123'").then((res)=>{
consol.log(res)//這裏的r是響應結果})
fetch("http://www.baidu.com").then(
(res)=>{
console.log(res);//是一個綜合各類方法的對象,並非請求的數據
})
fetch返回的是一個未處理的方法集合,咱們能夠經過這些方法獲得咱們想要的數據類型。若是咱們想要json格式,就執行response.json(),若是咱們想要字符串就response.text()
axios
一、從瀏覽器中建立 XMLHttpRequest
二、從 node.js 發出 http 請求
三、支持 Promise API
四、攔截請求和響應
五、轉換請求和響應數據
六、自動轉換JSON數據
七、客戶端支持防止CSRF/XSRF
fetch:
符合關注分離,沒有將輸入、輸出和用事件來跟蹤的狀態混雜在一個對象裏
更加底層,提供的API豐富(request, response)
脫離了XHR,是ES規範裏新的實現方式
一、fetchtch只對網絡請求報錯,對400,500都當作成功的請求,須要封裝去處理
二、fetch默認不會帶cookie,須要添加配置項
三、fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實
現的超時控制並不能阻止請求過程繼續在後臺運行,形成了量的浪費
四、fetch沒有辦法原生監測請求的進度,而XHR能夠