網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
(在構(gòu)造函數(shù)中)調(diào)用 super(props) 的目的是什么
在 super()
被調(diào)用之前,子類是不能使用 this
的,在 ES2015 中,子類必須在 constructor
中調(diào)用 super()
。傳遞 props
給 super()
的原因則是便于(在子類中)能在 constructor
訪問(wèn) this.props
。
你對(duì)【單一數(shù)據(jù)源】有什么理解
redux使用 store將程序的整個(gè)狀態(tài)存儲(chǔ)在同一個(gè)地方,因此所有組件的狀態(tài)都存儲(chǔ)在 Store 中,并且它們從 Store 本身接收更新。單一狀態(tài)樹可以更容易地跟蹤隨時(shí)間的變化,并調(diào)試或檢查程序
前端react面試題詳細(xì)解答
什么是控制組件?
在 HTML 中,表單元素如 <input>
、<textarea>
和<select>
通常維護(hù)自己的狀態(tài),并根據(jù)用戶輸入進(jìn)行更新。當(dāng)用戶提交表單時(shí),來(lái)自上述元素的值將隨表單一起發(fā)送。
而 React 的工作方式則不同。包含表單的組件將跟蹤其狀態(tài)中的輸入值,并在每次回調(diào)函數(shù)(例如onChange
)觸發(fā)時(shí)重新渲染組件,因?yàn)闋顟B(tài)被更新。以這種方式由 React 控制其值的輸入表單元素稱為受控組件。
hooks 為什么不能放在條件判斷里
以 setState 為例,在 react 內(nèi)部,每個(gè)組件(Fiber)的 hooks 都是以鏈表的形式存在 memoizeState 屬性中
update 階段,每次調(diào)用 setState,鏈表就會(huì)執(zhí)行 next 向后移動(dòng)一步。如果將 setState 寫在條件判斷中,假設(shè)條件判斷不成立,沒有執(zhí)行里面的 setState 方法,會(huì)導(dǎo)致接下來(lái)所有的 setState 的取值出現(xiàn)偏移,從而導(dǎo)致異常發(fā)生。
Redux內(nèi)部原理 內(nèi)部怎么實(shí)現(xiàn)dispstch一個(gè)函數(shù)的
以
redux-thunk
中間件作為例子,下面就是thunkMiddleware
函數(shù)的代碼
// 部分轉(zhuǎn)為ES5代碼,運(yùn)行middleware函數(shù)會(huì)返回一個(gè)新的函數(shù),如下:
return ({ dispatch, getState }) => {
// next實(shí)際就是傳入的dispatch
return function (next) {
return function (action) {
// redux-thunk核心
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
};
}
redux-thunk
庫(kù)內(nèi)部源碼非常的簡(jiǎn)單,允許action
是一個(gè)函數(shù),同時(shí)支持參數(shù)傳遞,否則調(diào)用方法不變
-
redux
創(chuàng)建Store
:通過(guò)combineReducers
函數(shù)合并reducer
函數(shù),返回一個(gè)新的函數(shù)combination
(這個(gè)函數(shù)負(fù)責(zé)循環(huán)遍歷運(yùn)行reducer
函數(shù),返回全部state
)。將這個(gè)新函數(shù)作為參數(shù)傳入createStore
函數(shù),函數(shù)內(nèi)部通過(guò)dispatch,初始化運(yùn)行傳入的combination
,state生成,返回store對(duì)象 -
redux
中間件:applyMiddleware
函數(shù)中間件的主要目的就是修改dispatch
函數(shù),返回經(jīng)過(guò)中間件處理的新的dispatch
函數(shù) -
redux
使用:實(shí)際就是再次調(diào)用循環(huán)遍歷調(diào)用reducer
函數(shù),更新state
使用 React Hooks 好處是啥?
首先,Hooks 通常支持提取和重用跨多個(gè)組件通用的有狀態(tài)邏輯,而無(wú)需承擔(dān)高階組件或渲染 props
的負(fù)擔(dān)。Hooks
可以輕松地操作函數(shù)組件的狀態(tài),而不需要將它們轉(zhuǎn)換為類組件。
Hooks 在類中不起作用,通過(guò)使用它們,咱們可以完全避免使用生命周期方法,例如 componentDidMount
、componentDidUpdate
、componentWillUnmount
。相反,使用像useEffect
這樣的內(nèi)置鉤子。
組件之間傳值
-
父組件給子組件傳值
在父組件中用標(biāo)簽屬性的=形式傳值
在子組件中使用props來(lái)獲取值
-
子組件給父組件傳值
在組件中傳遞一個(gè)函數(shù)
在子組件中用props來(lái)獲取傳遞的函數(shù),然后執(zhí)行該函數(shù)
在執(zhí)行函數(shù)的時(shí)候把需要傳遞的值當(dāng)成函數(shù)的實(shí)參進(jìn)行傳遞
-
兄弟組件之間傳值
利用父組件
先把數(shù)據(jù)通過(guò) 【子組件】===》【父組件】
然后在數(shù)據(jù)通過(guò) 【父組件】===〉【子組件】
消息訂閱
使用PubSubJs插件
React diff 算法的原理是什么?
實(shí)際上,diff 算法探討的就是虛擬 DOM 樹發(fā)生變化后,生成 DOM 樹更新補(bǔ)丁的方式。它通過(guò)對(duì)比新舊兩株虛擬 DOM 樹的變更差異,將更新補(bǔ)丁作用于真實(shí) DOM,以最小成本完成視圖更新。 具體的流程如下:
-
真實(shí)的 DOM 首先會(huì)映射為虛擬 DOM;
-
當(dāng)虛擬 DOM 發(fā)生變化后,就會(huì)根據(jù)差距計(jì)算生成 patch,這個(gè) patch 是一個(gè)結(jié)構(gòu)化的數(shù)據(jù),內(nèi)容包含了增加、更新、移除等;
-
根據(jù) patch 去更新真實(shí)的 DOM,反饋到用戶的界面上。
一個(gè)簡(jiǎn)單的例子:
import React from 'react'
export default class ExampleComponent extends React.Component {
render() {
if(this.props.isVisible) {
return <div className="visible">visbile</div>;
}
return <div className="hidden">hidden</div>;
}
}
這里,首先假定 ExampleComponent 可見,然后再改變它的狀態(tài),讓它不可見 。映射為真實(shí)的 DOM 操作是這樣的,React 會(huì)創(chuàng)建一個(gè) div 節(jié)點(diǎn)。
<div class="visible">visbile</div>
當(dāng)把 visbile 的值變?yōu)?false 時(shí),就會(huì)替換 class 屬性為 hidden,并重寫內(nèi)部的 innerText 為 hidden。這樣一個(gè)生成補(bǔ)丁、更新差異的過(guò)程統(tǒng)稱為 diff 算法。
diff算法可以總結(jié)為三個(gè)策略,分別從樹、組件及元素三個(gè)層面進(jìn)行復(fù)雜度的優(yōu)化:
策略一:忽略節(jié)點(diǎn)跨層級(jí)操作場(chǎng)景,提升比對(duì)效率。(基于樹進(jìn)行對(duì)比)
這一策略需要進(jìn)行樹比對(duì),即對(duì)樹進(jìn)行分層比較。樹比對(duì)的處理手法是非常“暴力”的,即兩棵樹只對(duì)同一層次的節(jié)點(diǎn)進(jìn)行比較,如果發(fā)現(xiàn)節(jié)點(diǎn)已經(jīng)不存在了,則該節(jié)點(diǎn)及其子節(jié)點(diǎn)會(huì)被完全刪除掉,不會(huì)用于進(jìn)一步的比較,這就提升了比對(duì)效率。
策略二:如果組件的 class 一致,則默認(rèn)為相似的樹結(jié)構(gòu),否則默認(rèn)為不同的樹結(jié)構(gòu)。(基于組件進(jìn)行對(duì)比)
在組件比對(duì)的過(guò)程中:
- 如果組件是同一類型則進(jìn)行樹比對(duì);
- 如果不是則直接放入補(bǔ)丁中。
只要父組件類型不同,就會(huì)被重新渲染。這也就是為什么 shouldComponentUpdate、PureComponent 及 React.memo 可以提高性能的原因。
策略三:同一層級(jí)的子節(jié)點(diǎn),可以通過(guò)標(biāo)記 key 的方式進(jìn)行列表對(duì)比。(基于節(jié)點(diǎn)進(jìn)行對(duì)比)
元素比對(duì)主要發(fā)生在同層級(jí)中,通過(guò)標(biāo)記節(jié)點(diǎn)操作生成補(bǔ)丁。節(jié)點(diǎn)操作包含了插入、移動(dòng)、刪除等。其中節(jié)點(diǎn)重新排序同時(shí)涉及插入、移動(dòng)、刪除三個(gè)操作,所以效率消耗最大,此時(shí)策略三起到了至關(guān)重要的作用。通過(guò)標(biāo)記 key 的方式,React 可以直接移動(dòng) DOM 節(jié)點(diǎn),降低內(nèi)耗。
在調(diào)用setState 之后發(fā)生了什么
-
狀態(tài)合并,觸發(fā)調(diào)和:
setState函數(shù)之后,會(huì)將傳入的參數(shù)對(duì)象與當(dāng)前的狀態(tài)合并,然后出發(fā)調(diào)用過(guò)程
-
根據(jù)新的狀態(tài)構(gòu)建虛擬dom樹
經(jīng)過(guò)調(diào)和過(guò)程,react會(huì)高效的根據(jù)新的狀態(tài)構(gòu)建虛擬DOM樹,準(zhǔn)備渲染整個(gè)UI頁(yè)面
-
計(jì)算新老樹節(jié)點(diǎn)差異,最小化渲染
得倒新的虛擬DOM樹后,會(huì)計(jì)算出新老樹的節(jié)點(diǎn)差異,會(huì)根據(jù)差異對(duì)界面進(jìn)行最小化渲染
-
按需更新
在差異話計(jì)算中,react可以相對(duì)準(zhǔn)確的知道哪些位置發(fā)生了改變以及該如何改變,這保證按需更新,而不是宣布重新渲染
hooks父子傳值
父?jìng)髯?在父組件中用useState聲明數(shù)據(jù)
const [ data, setData ] = useState(false)
把數(shù)據(jù)傳遞給子組件
<Child data={data} />
子組件接收
export default function (props) {
const { data } = props
console.log(data)
}
子傳父
子傳父可以通過(guò)事件方法傳值,和父?jìng)髯佑悬c(diǎn)類似。
在父組件中用useState聲明數(shù)據(jù)
const [ data, setData ] = useState(false)
把更新數(shù)據(jù)的函數(shù)傳遞給子組件
<Child setData={setData} />
子組件中觸發(fā)函數(shù)更新數(shù)據(jù),就會(huì)直接傳遞給父組件
export default function (props) {
const { setData } = props
setData(true)
}
如果存在多個(gè)層級(jí)的數(shù)據(jù)傳遞,也可依照此方法依次傳遞
// 多層級(jí)用useContext
const User = () => {
// 直接獲取,不用回調(diào)
const { user, setUser } = useContext(UserContext);
return <Avatar user={user} setUser={setUser} />;
};
Hooks可以取代 render props
和高階組件嗎?
通常,render props
和高階組件僅渲染一個(gè)子組件。React團(tuán)隊(duì)認(rèn)為,Hooks 是服務(wù)此用例的更簡(jiǎn)單方法。
這兩種模式仍然有一席之地(例如,一個(gè)虛擬的 scroller
組件可能有一個(gè) renderItem prop
,或者一個(gè)可視化的容器組件可能有它自己的 DOM 結(jié)構(gòu))。但在大多數(shù)情況下,Hooks 就足夠了,可以幫助減少樹中的嵌套。
React 高階組件、Render props、hooks 有什么區(qū)別,為什么要不斷迭代
這三者是目前react解決代碼復(fù)用的主要方式:
- 高階組件(HOC)是 React 中用于復(fù)用組件邏輯的一種高級(jí)技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計(jì)模式。具體而言,高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。
- render props是指一種在 React 組件之間使用一個(gè)值為函數(shù)的 prop 共享代碼的簡(jiǎn)單技術(shù),更具體的說(shuō),render prop 是一個(gè)用于告知組件需要渲染什么內(nèi)容的函數(shù) prop。
- 通常,render props 和高階組件只渲染一個(gè)子節(jié)點(diǎn)。讓 Hook 來(lái)服務(wù)這個(gè)使用場(chǎng)景更加簡(jiǎn)單。這兩種模式仍有用武之地,(例如,一個(gè)虛擬滾動(dòng)條組件或許會(huì)有一個(gè) renderltem 屬性,或是一個(gè)可見的容器組件或許會(huì)有它自己的 DOM 結(jié)構(gòu))。但在大部分場(chǎng)景下,Hook 足夠了,并且能夠幫助減少嵌套。
(1)HOC 官方解釋∶
高階組件(HOC)是 React 中用于復(fù)用組件邏輯的一種高級(jí)技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計(jì)模式。
簡(jiǎn)言之,HOC是一種組件的設(shè)計(jì)模式,HOC接受一個(gè)組件和額外的參數(shù)(如果需要),返回一個(gè)新的組件。HOC 是純函數(shù),沒有副作用。
// hoc的定義
function withSubscription(WrappedComponent, selectData) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
data: selectData(DataSource, props)
};
}
// 一些通用的邏輯處理
render() {
// ... 并使用新數(shù)據(jù)渲染被包裝的組件!
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
// 使用
const BlogPostWithSubscription = withSubscription(BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id));
HOC的優(yōu)缺點(diǎn)∶
- 優(yōu)點(diǎn)∶ 邏輯服用、不影響被包裹組件的內(nèi)部邏輯。
- 缺點(diǎn)∶ hoc傳遞給被包裹組件的props容易和被包裹后的組件重名,進(jìn)而被覆蓋
(2)Render props 官方解釋∶
"render prop"是指一種在 React 組件之間使用一個(gè)值為函數(shù)的 prop 共享代碼的簡(jiǎn)單技術(shù)
具有render prop 的組件接受一個(gè)返回React元素的函數(shù),將render的渲染邏輯注入到組件內(nèi)部。在這里,"render"的命名可以是任何其他有效的標(biāo)識(shí)符。
// DataProvider組件內(nèi)部的渲染邏輯如下
class DataProvider extends React.Components {
state = {
name: 'Tom'
}
render() {
return (
<div>
<p>共享數(shù)據(jù)組件自己內(nèi)部的渲染邏輯</p>
{ this.props.render(this.state) } </div>
);
}
}
// 調(diào)用方式
<DataProvider render={data => (
<h1>Hello {data.name}</h1>
)}/>
由此可以看到,render props的優(yōu)缺點(diǎn)也很明顯∶
- 優(yōu)點(diǎn):數(shù)據(jù)共享、代碼復(fù)用,將組件內(nèi)的state作為props傳遞給調(diào)用者,將渲染邏輯交給調(diào)用者。
- 缺點(diǎn):無(wú)法在 return 語(yǔ)句外訪問(wèn)數(shù)據(jù)、嵌套寫法不夠優(yōu)雅
(3)Hooks 官方解釋∶
Hook是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。通過(guò)自定義hook,可以復(fù)用代碼邏輯。
// 自定義一個(gè)獲取訂閱數(shù)據(jù)的hook
function useSubscription() {
const data = DataSource.getComments();
return [data];
}
//
function CommentList(props) {
const {data} = props;
const [subData] = useSubscription();
...
}
// 使用
<CommentList data='hello' />
以上可以看出,hook解決了hoc的prop覆蓋的問(wèn)題,同時(shí)使用的方式解決了render props的嵌套地獄的問(wèn)題。hook的優(yōu)點(diǎn)如下∶
- 使用直觀;
- 解決hoc的prop 重名問(wèn)題;
- 解決render props 因共享數(shù)據(jù) 而出現(xiàn)嵌套地獄的問(wèn)題;
- 能在return之外使用數(shù)據(jù)的問(wèn)題。
需要注意的是:hook只能在組件頂層使用,不可在分支語(yǔ)句中使用。、
哪些方法會(huì)觸發(fā) React 重新渲染?重新渲染 render 會(huì)做些什么?
(1)哪些方法會(huì)觸發(fā) react 重新渲染?
- setState()方法被調(diào)用
setState 是 React 中最常用的命令,通常情況下,執(zhí)行 setState 會(huì)觸發(fā) render。但是這里有個(gè)點(diǎn)值得關(guān)注,執(zhí)行 setState 的時(shí)候不一定會(huì)重新渲染。當(dāng) setState 傳入 null 時(shí),并不會(huì)觸發(fā) render。
class App extends React.Component {
state = {
a: 1
};
render() {
console.log("render");
return (
<React.Fragement>
<p>{this.state.a}</p>
<button
onClick={() => { this.setState({ a: 1 }); // 這里并沒有改變 a 的值 }} > Click me </button>
<button onClick={() => this.setState(null)}>setState null</button>
<Child />
</React.Fragement>
);
}
}
- 父組件重新渲染
只要父組件重新渲染了,即使傳入子組件的 props 未發(fā)生變化,那么子組件也會(huì)重新渲染,進(jìn)而觸發(fā) render
(2)重新渲染 render 會(huì)做些什么?
- 會(huì)對(duì)新舊 VNode 進(jìn)行對(duì)比,也就是我們所說(shuō)的Diff算法。
- 對(duì)新舊兩棵樹進(jìn)行一個(gè)深度優(yōu)先遍歷,這樣每一個(gè)節(jié)點(diǎn)都會(huì)一個(gè)標(biāo)記,在到深度遍歷的時(shí)候,每遍歷到一和個(gè)節(jié)點(diǎn),就把該節(jié)點(diǎn)和新的節(jié)點(diǎn)樹進(jìn)行對(duì)比,如果有差異就放到一個(gè)對(duì)象里面
- 遍歷差異對(duì)象,根據(jù)差異的類型,根據(jù)對(duì)應(yīng)對(duì)規(guī)則更新VNode
React 的處理 render 的基本思維模式是每次一有變動(dòng)就會(huì)去重新渲染整個(gè)應(yīng)用。在 Virtual DOM 沒有出現(xiàn)之前,最簡(jiǎn)單的方法就是直接調(diào)用 innerHTML。Virtual DOM厲害的地方并不是說(shuō)它比直接操作 DOM 快,而是說(shuō)不管數(shù)據(jù)怎么變,都會(huì)盡量以最小的代價(jià)去更新 DOM。React 將 render 函數(shù)返回的虛擬 DOM 樹與老的進(jìn)行比較,從而確定 DOM 要不要更新、怎么更新。當(dāng) DOM 樹很大時(shí),遍歷兩棵樹進(jìn)行各種比對(duì)還是相當(dāng)耗性能的,特別是在頂層 setState 一個(gè)微小的修改,默認(rèn)會(huì)去遍歷整棵樹。盡管 React 使用高度優(yōu)化的 Diff 算法,但是這個(gè)過(guò)程仍然會(huì)損耗性能.
對(duì) React context 的理解
在React中,數(shù)據(jù)傳遞一般使用props傳遞數(shù)據(jù),維持單向數(shù)據(jù)流,這樣可以讓組件之間的關(guān)系變得簡(jiǎn)單且可預(yù)測(cè),但是單項(xiàng)數(shù)據(jù)流在某些場(chǎng)景中并不適用。單純一對(duì)的父子組件傳遞并無(wú)問(wèn)題,但要是組件之間層層依賴深入,props就需要層層傳遞顯然,這樣做太繁瑣了。
Context 提供了一種在組件之間共享此類值的方式,而不必顯式地通過(guò)組件樹的逐層傳遞 props。
可以把context當(dāng)做是特定一個(gè)組件樹內(nèi)共享的store,用來(lái)做數(shù)據(jù)傳遞。簡(jiǎn)單說(shuō)就是,當(dāng)你不想在組件樹中通過(guò)逐層傳遞props或者state的方式來(lái)傳遞數(shù)據(jù)時(shí),可以使用Context來(lái)實(shí)現(xiàn)跨層級(jí)的組件數(shù)據(jù)傳遞。
JS的代碼塊在執(zhí)行期間,會(huì)創(chuàng)建一個(gè)相應(yīng)的作用域鏈,這個(gè)作用域鏈記錄著運(yùn)行時(shí)JS代碼塊執(zhí)行期間所能訪問(wèn)的活動(dòng)對(duì)象,包括變量和函數(shù),JS程序通過(guò)作用域鏈訪問(wèn)到代碼塊內(nèi)部或者外部的變量和函數(shù)。
假如以JS的作用域鏈作為類比,React組件提供的Context對(duì)象其實(shí)就好比一個(gè)提供給子組件訪問(wèn)的作用域,而 Context對(duì)象的屬性可以看成作用域上的活動(dòng)對(duì)象。由于組件 的 Context 由其父節(jié)點(diǎn)鏈上所有組件通 過(guò) getChildContext()返回的Context對(duì)象組合而成,所以,組件通過(guò)Context是可以訪問(wèn)到其父組件鏈上所有節(jié)點(diǎn)組件提供的Context的屬性。
React最新的?命周期是怎樣的?
React 16之后有三個(gè)?命周期被廢棄(但并未刪除)
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
官?計(jì)劃在17版本完全刪除這三個(gè)函數(shù),只保留UNSAVE_前綴的三個(gè)函數(shù),?的是為了向下兼容,但是對(duì)于開發(fā)者??應(yīng)該盡量避免使?他們,?是使?新增的?命周期函數(shù)替代它們。
?前React16.8+的?命周期分為三個(gè)階段,分別是掛載階段、更新階段、卸載階段。
掛載階段:
- constructor:構(gòu)造函數(shù),最先被執(zhí)?,我們通常在構(gòu)造函數(shù)?初始化state對(duì)象或者給?定義?法綁定this;
- getDerivedStateFromProps:static getDerivedStateFromProps(nextProps, prevState),這是個(gè)靜態(tài)?法,當(dāng)我們接收到新的屬性想去修改我們state, 可以使?getDerivedStateFromProps
- render:render函數(shù)是純函數(shù),只返回需要渲染的東?,不應(yīng)該包含其它的業(yè)務(wù)邏輯,可以返回原?的DOM、React組件、Fragment、Portals、字符串和數(shù)字、 Boolean和null等內(nèi)容;
- componentDidMount:組件裝載之后調(diào)?,此時(shí)我們可以獲取到DOM節(jié)點(diǎn)并操作,?如對(duì)canvas,svg的操作,服務(wù)器請(qǐng)求,訂閱都可以寫在這個(gè)??,但是記得在componentWillUnmount中取消訂閱;
更新階段:
- getDerivedStateFromProps: 此?法在更新個(gè)掛載階段都可能會(huì)調(diào)?;
- shouldComponentUpdate:shouldComponentUpdate(nextProps, nextState),有兩個(gè)參數(shù)nextProps和nextState,表示新的屬性和變化之后的state,返回?個(gè)布爾值,true表示會(huì)觸發(fā)重新渲染,false表示不會(huì)觸發(fā)重新渲染,默認(rèn)返回true,我們通常利?此?命周期來(lái)優(yōu)化React程序性能;
- render:更新階段也會(huì)觸發(fā)此?命周期;
- getSnapshotBeforeUpdate:getSnapshotBeforeUpdate(prevProps, prevState),這個(gè)?法在render之后,componentDidUpdate之前調(diào)?,有兩個(gè)參數(shù)prevProps和prevState,表示之前的屬性和之前的state,這個(gè)函數(shù)有?個(gè)返回值,會(huì)作為第三個(gè)參數(shù)傳給componentDidUpdate,如果你不想要返回值,可以返回null,此?命周期必須與componentDidUpdate搭配使?;
- componentDidUpdate:componentDidUpdate(prevProps, prevState, snapshot),該?法在getSnapshotBeforeUpdate?法之后被調(diào)?,有三個(gè)參數(shù)prevProps,prevState,snapshot,表示之前的props,之前的state,和snapshot。第三個(gè)參數(shù)是getSnapshotBeforeUpdate返回的,如果觸發(fā)某些回調(diào)函數(shù)時(shí)需要?到DOM元素的狀態(tài),則將對(duì)?或計(jì)算的過(guò)程遷移?getSnapshotBeforeUpdate,然后在componentDidUpdate中統(tǒng)?觸發(fā)回調(diào)或更新狀態(tài)。
卸載階段:
-componentWillUnmount:當(dāng)我們的組件被卸載或者銷毀了就會(huì)調(diào)?,我們可以在這個(gè)函數(shù)?去清除?些定時(shí)器,取消?絡(luò)請(qǐng)求,清理?效的DOM元素等垃圾清理?作。
總結(jié):
- componentWillMount:在渲染之前執(zhí)行,用于根組件中的 App 級(jí)配置;
- componentDidMount:在第一次渲染之后執(zhí)行,可以在這里做AJAX請(qǐng)求,DOM的操作或狀態(tài)更新以及設(shè)置事件監(jiān)聽器;
- componentWillReceiveProps:在初始化render的時(shí)候不會(huì)執(zhí)行,它會(huì)在組件接受到新的狀態(tài)(Props)時(shí)被觸發(fā),一般用于父組件狀態(tài)更新時(shí)子組件的重新渲染
- shouldComponentUpdate:確定是否更新組件。默認(rèn)情況下,它返回true。如果確定在state或props更新后組件不需要在重新渲染,則可以返回false,這是一個(gè)提高性能的方法;
- componentWillUpdate:在shouldComponentUpdate返回true確定要更新組件之前件之前執(zhí)行;
- componentDidUpdate:它主要用于更新DOM以響應(yīng)props或state更改;
- componentWillUnmount:它用于取消任何的網(wǎng)絡(luò)請(qǐng)求,或刪除與組件關(guān)聯(lián)的所有事件監(jiān)聽器。
setState之后 發(fā)生了什么?
- (1)代碼中調(diào)用 setState 函數(shù)之后,React 會(huì)將傳入的參數(shù)對(duì)象與組件當(dāng)前的狀態(tài)合并,然后觸發(fā)所謂的調(diào)和過(guò)程(Reconciliation)。
- (2)經(jīng)過(guò)調(diào)和過(guò)程,React 會(huì)以相對(duì)高效的方式根據(jù)新的狀態(tài)構(gòu)建 React 元素樹并且著手重新渲染整個(gè) UI 界面;
- (3)在 React 得到元素樹之后,React 會(huì)自動(dòng)計(jì)算出新的樹與老樹的節(jié)點(diǎn)差異,然后根據(jù)差異對(duì)界面進(jìn)行最小化重渲染;
- (4)在差異計(jì)算算法中,React 能夠相對(duì)精確地知道哪些位置發(fā)生了改變以及應(yīng)該如何改變,這就保證了按需更新,而不是全部重新渲染。
setState的調(diào)用會(huì)引起React的更新生命周期的4個(gè)函數(shù)執(zhí)行。
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
react 實(shí)現(xiàn)一個(gè)全局的 dialog
import React, { Component } from 'react';
import { is, fromJS } from 'immutable';
import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import './dialog.css';
let defaultState = {
alertStatus:false,
alertTip:"提示",
closeDialog:function(){},
childs:''
}
class Dialog extends Component{
state = {
...defaultState
};
// css動(dòng)畫組件設(shè)置為目標(biāo)組件
FirstChild = props => {
const childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
}
//打開彈窗
open =(options)=>{
options = options || {};
options.alertStatus = true;
var props = options.props || {};
var childs = this.renderChildren(props,options.childrens) || '';
console.log(childs);
this.setState({
...defaultState,
...options,
childs
})
}
//關(guān)閉彈窗
close(){
this.state.closeDialog();
this.setState({
...defaultState
})
}
renderChildren(props,childrens) {
//遍歷所有子組件
var childs = [];
childrens = childrens || [];
var ps = {
...props, //給子組件綁定props
_close:this.close //給子組件也綁定一個(gè)關(guān)閉彈窗的事件
};
childrens.forEach((currentItem,index) => {
childs.push(React.createElement(
currentItem,
{
...ps,
key:index
}
));
})
return childs;
}
shouldComponentUpdate(nextProps, nextState){
return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
}
render(){
return (
<ReactCSSTransitionGroup
component={this.FirstChild}
transitionName='hide'
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
<div className="dialog-con" style={this.state.alertStatus? {display:'block'}:{display:'none'}}>
{this.state.childs} </div>
</ReactCSSTransitionGroup>
);
}
}
let div = document.createElement('div');
let props = {
};
document.body.appendChild(div);
let Box = ReactD
子類:
//子類jsx
import React, { Component } from 'react';
class Child extends Component {
constructor(props){
super(props);
this.state = {date: new Date()};
}
showValue=()=>{
this.props.showValue && this.props.showValue()
}
render() {
return (
<div className="Child">
<div className="content">
Child <button onClick={this.showValue}>調(diào)用父的方法</button>
</div>
</div>
);
}
}
export default Child;
css:
.dialog-con{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
React的嚴(yán)格模式如何使用,有什么用處?
StrictMode
是一個(gè)用來(lái)突出顯示應(yīng)用程序中潛在問(wèn)題的工具。與 Fragment
一樣,StrictMode
不會(huì)渲染任何可見的 UI。它為其后代元素觸發(fā)額外的檢查和警告。
可以為應(yīng)用程序的任何部分啟用嚴(yán)格模式。例如:
import React from 'react';
function ExampleApplication() {
return (
<div>
<Header />
<React.StrictMode>
<div>
<ComponentOne />
<ComponentTwo />
</div>
</React.StrictMode>
<Footer />
</div>
);
}
在上述的示例中,不會(huì)對(duì) Header
和 Footer
組件運(yùn)行嚴(yán)格模式檢查。但是,ComponentOne
和 ComponentTwo
以及它們的所有后代元素都將進(jìn)行檢查。
StrictMode
目前有助于:
- 識(shí)別不安全的生命周期
- 關(guān)于使用過(guò)時(shí)字符串 ref API 的警告
- 關(guān)于使用廢棄的 findDOMNode 方法的警告
- 檢測(cè)意外的副作用
- 檢測(cè)過(guò)時(shí)的 context API
class類的key改了,會(huì)發(fā)生什么,會(huì)執(zhí)行哪些周期函數(shù)?
在開發(fā)過(guò)程中,我們需要保證某個(gè)元素的 key 在其同級(jí)元素中具有唯一性。在 React Diff 算法中 React 會(huì)借助元素的 Key 值來(lái)判斷該元素是新近創(chuàng)建的還是被移動(dòng)而來(lái)的元素,從而減少不必要的元素重渲染。此外,React 還需要借助 Key 值來(lái)判斷元素與本地狀態(tài)的關(guān)聯(lián)關(guān)系,因此我們絕不可忽視轉(zhuǎn)換函數(shù)中 Key 的重要性。
答:componentWillMount componentDidMount render
React.forwardRef有什么用
forwardRef
- 使用
forwardRef
(forward
在這里是「?jìng)鬟f」的意思)后,就能跨組件傳遞ref
。 - 在例子中,我們將
inputRef
從Form
跨組件傳遞到MyInput
中,并與input
產(chǎn)生關(guān)聯(lián)
const MyInput = forwardRef((props, ref) => {
return <input {...props} ref={ref} />;
});
function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<MyInput ref={inputRef} />
<button onClick={handleClick}>
Focus the input
</button>
</>
);
}
useImperativeHandle
除了「限制跨組件傳遞
ref
」外,還有一種「防止ref
失控的措施」,那就是useImperativeHandle
,他的邏輯是這樣的:既然「ref失控」
是由于「使用了不該被使用的DOM方法」(比如appendChild
),那我可以限制「ref
中只存在可以被使用的方法」。用useImperativeHandle
修改我們的MyInput組件:
const MyInput = forwardRef((props, ref) => {
const realInputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus() {
realInputRef.current.focus();
},
}));
return <input {...props} ref={realInputRef} />;
});
現(xiàn)在,Form
組件中通過(guò)inputRef.current
只能取到如下數(shù)據(jù)結(jié)構(gòu):
{
focus() {
realInputRef.current.focus();
},
}
就杜絕了
「開發(fā)者通過(guò)ref取到DOM后,執(zhí)行不該被使用的API,出現(xiàn)ref失控」
的情況
- 為了防止錯(cuò)用/濫用導(dǎo)致
ref
失控,React限制「默認(rèn)情況下,不能跨組件傳遞ref」
- 為了破除這種限制,可以使用
forwardRef
。 - 為了減少
ref
對(duì)DOM
的濫用,可以使用useImperativeHandle
限制ref
傳遞的數(shù)據(jù)結(jié)構(gòu)。
原文鏈接:https://blog.csdn.net/beifeng11996/article/details/127033765
相關(guān)推薦
- 2022-10-07 Docker容器操作方法詳解_docker
- 2022-07-14 Android實(shí)現(xiàn)手機(jī)多點(diǎn)觸摸畫圓_Android
- 2022-11-23 Python利用keyboard模塊實(shí)現(xiàn)鍵盤記錄操作_python
- 2023-08-01 頁(yè)面滾動(dòng)時(shí)隱藏element-ui下拉框/時(shí)間彈框
- 2024-02-17 自定義Matplotlib中的顏色映射(cmap)
- 2022-07-13 Stream的源碼簡(jiǎn)單解析
- 2024-04-06 npm install安裝插件很慢,解決方法
- 2022-03-23 C語(yǔ)言實(shí)現(xiàn)打印楊輝三角的方法詳細(xì)(三種方法)_C 語(yǔ)言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支