react取消捕获_React 面试指南 (上)
使用 React 進(jìn)行項(xiàng)目開(kāi)發(fā)也有好幾個(gè)項(xiàng)目了,趁著最近有空來(lái)對(duì) React 的知識(shí)做一個(gè)簡(jiǎn)單的復(fù)盤。
完整目錄概覽
- React 是單向數(shù)據(jù)流還是雙向數(shù)據(jù)流?它還有其他特點(diǎn)嗎?
- setState
- React 通過(guò)什么方式來(lái)更新數(shù)據(jù)
- React 不能直接修改 State 嗎?
- setState 是同步還是異步的?
- setState 小測(cè)
- React 生命周期
- constructor (構(gòu)造函數(shù))
- static getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidMount
- componentDidUpdate
- componentWillUnmount
- 生命周期階段
- 其他生命周期
- React 組件通信
- React.Context 怎么使用
- 函數(shù)組件是什么?與類組件有什么區(qū)別?
- Hooks
- Hook vs class
- Hooks 的使用
- 自定義 Hook 的使用
- Hook 使用約束
- class 組件與 Hook 之間的映射與轉(zhuǎn)換
- 生命周期
- Hooks 沒(méi)有實(shí)現(xiàn)的生命周期鉤子
- 轉(zhuǎn)換實(shí)例變量
- 強(qiáng)制更新 Hook 組件
- 獲取舊的 props 和 state
- 受控組件與非受控組件的區(qū)別
- Portals 是什么?
React 是單向數(shù)據(jù)流還是雙向數(shù)據(jù)流?它還有其他特點(diǎn)嗎?
React 是單向數(shù)據(jù)流,數(shù)據(jù)是從上向下流。它的其他主要特點(diǎn)時(shí):
- 數(shù)據(jù)驅(qū)動(dòng)視圖
- 聲明式編寫 UI
- 組件化開(kāi)發(fā)
React 通過(guò)什么方式來(lái)更新數(shù)據(jù)
React 是通過(guò) setState 來(lái)更新數(shù)據(jù)的。調(diào)用多個(gè) setState 不會(huì)立即更新數(shù)據(jù),而會(huì)批量延遲更新后再將數(shù)據(jù)合并。
除了 setState 外還可以使用 forceUpdate 跳過(guò)當(dāng)前組件的 shouldComponentUpdate diff,強(qiáng)制觸發(fā)組件渲染(避免使用該方式)。
React 不能直接修改 State 嗎?
setState 是同步還是異步的?
出于性能的考慮,React 可能會(huì)把多個(gè) setState 合并成一個(gè)調(diào)用。
React 內(nèi)有個(gè) batchUpdate(批量更新) 的機(jī)制,在 React 可以控制的區(qū)域 (如組件生命周期、React 封裝的事件處理器) 設(shè)置標(biāo)識(shí)位 isBatchingUpdate 來(lái)決定是否觸發(fā)更新。
比如在 React 中注冊(cè)的 onClick 事件或是 componentDidMount 中直接使用 setState 都是異步的。若想拿到觸發(fā)更新后的值,可以給 setState 第二個(gè)參數(shù)傳遞一個(gè)函數(shù),該函數(shù)在數(shù)據(jù)更新后會(huì)觸發(fā)的回調(diào)函數(shù),函數(shù)的參數(shù)就是更新后最新的值。
不受 React 控制的代碼快中使用 setState 是同步的,比如在 setTimeout 或是原生的事件監(jiān)聽(tīng)器中使用。
setState 小測(cè)
輸出以下結(jié)果:
componentDidMount() {this.setState({ count: this.state.count + 1 });console.log("1 -->", this.state.count);this.setState({ count: this.state.count + 1 });console.log("2 -->", this.state.count);setTimeout(() => {this.setState({ count: this.state.count + 1 });console.log("3 -->", this.state.count);}, 0);setTimeout(() => {this.setState({ count: this.state.count + 1 });console.log("4 -->", this.state.count);}, 0); }輸出結(jié)果為:
1 --> 0 2 --> 0 3 --> 2 4 --> 3解答: 調(diào)用 setState 后不會(huì)立即更新 state,開(kāi)頭兩次調(diào)用會(huì)被異步合并調(diào)用,因此只有一次調(diào)用。一輪事件循環(huán)結(jié)束后,調(diào)用第 3、4 次 setState。由于在 setTimeout 中調(diào)用是同步更新的,因此都能正常的疊加數(shù)據(jù)。
React 生命周期
React 的生命周期主要是指組件在特定階段會(huì)執(zhí)行的函數(shù)。以下是 class 組件的部分生命周期圖譜:
React 生命周期速查圖從上圖可以看出:React 的生命周期按照類型劃分,可分為 掛載時(shí)(Mounting)、更新時(shí)(Updating)、卸載時(shí)(Unmounting) 。圖中的生命周期函數(shù)效果如下:
constructor (構(gòu)造函數(shù))
- 觸發(fā)條件: 組件初始化時(shí)
- 是否可以使用 setState: X
- 使用場(chǎng)景: 初始化 state 或者對(duì)方法綁定 this
static getDerivedStateFromProps
Tips: 不常用方法- 觸發(fā)條件: 調(diào)用 render 函數(shù)之前
- 是否可以使用 setState: X
- 函數(shù)行為: 函數(shù)可以返回一個(gè)對(duì)象用于更新組件內(nèi)部的 state 數(shù)據(jù),若返回 null 則什么都不更新。
- 使用場(chǎng)景: 用于 state 依賴 props 的情況,也就是狀態(tài)派生。值得注意的是派生 state 會(huì)導(dǎo)致代碼冗余,并使組件難以維護(hù)。
shouldComponentUpdate
Tips: 不常用方法- 觸發(fā)條件: 當(dāng) props/state 發(fā)生變化
- 是否可以使用 setState: X
- 函數(shù)行為: 函數(shù)的返回值決定組件是否觸發(fā) render,返回值為 true 則觸發(fā)渲染,反之則阻止渲染。(組件內(nèi)不寫該函數(shù)的話,則調(diào)用默認(rèn)函數(shù)。默認(rèn)函數(shù)只會(huì)返回 true,即只要 props/state 發(fā)生變化,就更新組件)
- 使用場(chǎng)景: 組件的性能優(yōu)化,僅僅是淺比較 props 和 state 的變化的話,可以使用內(nèi)置的 PureComponent 來(lái)代替 Component 組件。
render
- 觸發(fā)條件: 渲染組件時(shí)
- 是否可以使用 setState: X
- 函數(shù)行為: 函數(shù)的返回值決定視圖的渲染效果
- 使用場(chǎng)景: class 組件中唯一必須要實(shí)現(xiàn)的生命周期函數(shù)。
getSnapshotBeforeUpdate
Tips: 不常用方法- 觸發(fā)條件: 在最近一次渲染輸出(提交到 DOM 節(jié)點(diǎn))之前調(diào)用
- 是否可以使用 setState: X
- 函數(shù)行為: 函數(shù)的返回值將傳入給 componentDidUpdate 第三個(gè)參數(shù)中。若只實(shí)現(xiàn)了該函數(shù),但沒(méi)有使用 componentDidUpdate 的話,React 將會(huì)在控制臺(tái)拋出警告
- 使用場(chǎng)景: 可以在組件發(fā)生更改之前從 DOM 中捕獲一些信息(例如,列表的滾動(dòng)位置)
componentDidMount
- 觸發(fā)條件: 組件掛載后(插入 DOM 樹中)立即調(diào)用
- 是否可以使用 setState: Y (可以直接調(diào)用,但會(huì)觸發(fā)額外渲染)
- 使用場(chǎng)景: 從網(wǎng)絡(luò)請(qǐng)求中獲取數(shù)據(jù)、訂閱事件等
componentDidUpdate
- 觸發(fā)條件: 組件更新完畢后(首次渲染不會(huì)觸發(fā))
- 是否可以使用 setState: Y (更新語(yǔ)句須放在條件語(yǔ)句中,不然可能會(huì)造成死循環(huán))
- 使用場(chǎng)景: 對(duì)比新舊值的變化,進(jìn)而判斷是否需要發(fā)送網(wǎng)絡(luò)請(qǐng)求。比如監(jiān)聽(tīng)路由的變化
componentWillUnmount
- 觸發(fā)條件: 組件卸載及銷毀之前直接調(diào)用
- 是否可以使用 setState: X
- 使用場(chǎng)景: 清除 timer,取消網(wǎng)絡(luò)請(qǐng)求或清除在 componentDidMount 中創(chuàng)建的訂閱等
生命周期階段
針對(duì) React 生命周期中函數(shù)的調(diào)用順序,筆者寫了一個(gè)簡(jiǎn)易的 Demo 用于演示: React 生命周期示例
React 組件掛載階段先后會(huì)觸發(fā) constuctor、static getDerivedStateFromProps、render、componentDidMount 函數(shù)。若 render 函數(shù)內(nèi)還有子組件存在的話,則會(huì)進(jìn)一步遞歸:
[Parent]: constuctor [Parent]: static getDerivedStateFromProps [Parent]: render [Children]: constuctor [Children]: static getDerivedStateFromProps [Children]: render [Children]: componentDidMount [Children]: 掛載階段結(jié)束! [Parent]: componentDidMount [Parent]: 掛載階段結(jié)束!React 組件更新階段主要是組件的 props 或 state 發(fā)生變化時(shí)觸發(fā)。若組件內(nèi)還子組件,則子組件會(huì)判斷是否也需要觸發(fā)更新。默認(rèn)情況下 component 組件是只要父組件發(fā)生了變化,子組件也會(huì)跟著變化。以下是更新父組件 state 數(shù)據(jù)時(shí)所觸發(fā)的生命周期函數(shù):
[Parent]: static getDerivedStateFromProps [Parent]: shouldComponentUpdate [Parent]: render [Children]: static getDerivedStateFromProps [Children]: shouldComponentUpdate [Children]: render [Children]: getSnapshotBeforeUpdate [Parent]: getSnapshotBeforeUpdate [Children]: componentDidUpdate [Children]: 更新階段結(jié)束! [Parent]: componentDidUpdate [Parent]: 更新階段結(jié)束!值得注意的是: 在本例 Demo 中沒(méi)有給子組件傳參,但子組件也觸發(fā)了渲染。但從應(yīng)用的角度上考慮,既然你子組件沒(méi)有需要更新的東西,那就沒(méi)有必要觸發(fā)渲染吧?
因此 Component 組件上可以使用 shouldComponentUpdate 或者將 Component 組件替換為 PureComponment 組件來(lái)做優(yōu)化。在生命周期圖中也可以看到: shouldComponentUpdate 返回 false 時(shí),將不再繼續(xù)觸發(fā)下面的函數(shù)。
有時(shí)你可能在某些情況下想主動(dòng)觸發(fā)渲染而又不被 shouldComponentUpdate 阻止渲染該怎么辦呢?可以使用 force-Update() 跳過(guò) shouldComponentUpdate 的 diff,進(jìn)而渲染視圖。(需要使用強(qiáng)制渲染的場(chǎng)景較少,一般不推薦這種方式進(jìn)行開(kāi)發(fā))
React 組件銷毀階段也沒(méi)啥好說(shuō)的了。父組件先觸發(fā)銷毀前的函數(shù),再逐層向下觸發(fā):
[Parent]: componentWillUnmount [Parent]: 卸載階段結(jié)束! [Children]: componentWillUnmount [Children]: 卸載階段結(jié)束!其他生命周期
除了上圖比較常見(jiàn)的生命周期外,還有一些過(guò)時(shí)的 API 就沒(méi)有額外介紹了。因?yàn)樗鼈兛赡茉谖磥?lái)的版本會(huì)被移除。
- UNSAFE_componentWillMount()
- UNSAFE_componentWillUpdate()
- UNSAFE_componentWillReceiveProps()
當(dāng)渲染過(guò)程,生命周期,或子組件的構(gòu)造函數(shù)中拋出錯(cuò)誤時(shí),會(huì)調(diào)用如下方法:
- static getDerivedStateFromError()
- componentDidCatch()
React 組件通信
React.Context 怎么使用
Context 可以共享對(duì)于組件樹而言是全局的數(shù)據(jù),比如全局主題、首選語(yǔ)言等。使用方式如下:
2. Context 對(duì)象中有一個(gè) Provider(提供者) 組件,Provider 組件接受一個(gè) value 屬性用以將數(shù)據(jù)傳遞給消費(fèi)組件。
<ThemeContext.Provider value="dark"><page /> </ThemeContext.Provider>3. 獲取 Context 提供的值可以通過(guò) contextType 或者 Consumer(消費(fèi)者) 組件中獲取。contextType 只能用于類組件,并且只能掛載一個(gè) Context:
class MyClass extends React.Component {componentDidMount() {let value = this.context;/* 在組件掛載完成后,使用 MyContext 的值執(zhí)行一些有副作用的操作 */}render() {let value = this.context;/* 基于 MyContext 的值進(jìn)行渲染 */} } MyClass.contextType = MyContext;若想給組件掛載多個(gè) Context, 或者在函數(shù)組件內(nèi)使用 Context 可以使用 Consumer 組件:
<ThemeContext.Consumer>{theme => (<UserContext.Consumer>{user => (<ProfilePage user={user} theme={theme} />)}</UserContext.Consumer>)}</ThemeContext.Consumer>Context 通常適用于傳遞較為簡(jiǎn)單的數(shù)據(jù)信息,若數(shù)據(jù)太過(guò)復(fù)雜,還是需要引入狀態(tài)管理(Redux/Mbox)。
函數(shù)組件是什么?與類組件有什么區(qū)別?
函數(shù)組件本質(zhì)上是一個(gè)純函數(shù),它接受 props 屬性,最后返回 JSX。
與類組件的差別在于: 它沒(méi)有實(shí)例、不能通過(guò) extends 繼承于其他方法、也沒(méi)有生命周期和 state。以前函數(shù)組件常作為無(wú)狀態(tài)組件,React 16.8+ 可以引入 Hooks 為函數(shù)組件支持狀態(tài)和副作用操作。
Hook vs class
類組件的不足:
- 狀態(tài)邏輯復(fù)用難,缺少?gòu)?fù)用機(jī)制。渲染屬性和高階組件導(dǎo)致層級(jí)冗余。
- 復(fù)雜組件變得難以理解。
- this 指向令人困擾。
Hooks 的優(yōu)點(diǎn):
- 自定義 Hook 方便復(fù)用狀態(tài)邏輯
- 副作用的關(guān)注點(diǎn)分離
- 函數(shù)組件沒(méi)有 this 問(wèn)題
Hooks 現(xiàn)有的不足:
- 不能完全取代 class 組件的生命周期,部分不常用的生命周期暫時(shí)沒(méi)有實(shí)現(xiàn)。
- Hooks 的運(yùn)作方式帶來(lái)了一定的學(xué)習(xí)成本,需要轉(zhuǎn)換現(xiàn)有的編程思維,增加了心智負(fù)擔(dān)。
Hooks 的使用
描述 Hooks 有哪些常用的方法和大致用途除此之外,useEffect 還可以返回一個(gè)函數(shù)用于做清除操作,這個(gè)清除操作時(shí)可選的。常用于清理訂閱事件、DOM 事件等。
// 綁定 DOM 事件 useEffect(() => {document.addEventListener('click', handleClick);// useEffect 回調(diào)函數(shù)的返回值是函數(shù)的話,當(dāng)組件卸載時(shí)會(huì)執(zhí)行該函數(shù)// 若沒(méi)有需要清除的東西,則可以忽略這一步驟return () => {document.removeEventListener('click', handleClick);}; }, [handleClick]);}, [handleClick]); ```3. useLayoutEffect: useEffect 的 effect 執(zhí)行的時(shí)機(jī)是在瀏覽器完成布局和繪制之后會(huì)延遲調(diào)用。若想要 DOM 變更的同時(shí)同步執(zhí)行 effect 的話可以使用 useLayoutEffect。它們之間只是執(zhí)行的時(shí)機(jī)不同,其他都一樣。
4. useContext: 接收一個(gè) Context 對(duì)象,并返回 Context 的當(dāng)前值。相當(dāng)于類組件的 static contextType = MyContext。
5. useReducer 是 useState 的代替方案,它的工作方式有點(diǎn)類似于 Redux,通過(guò)函數(shù)來(lái)操作 state。適合 state 邏輯較為復(fù)雜且包含多個(gè)子值,或是新的 state 依賴于舊的 state 的場(chǎng)景。
6. useMemo 主要用于性能優(yōu)化,它可以緩存變量的值,避免每次組件更新后都需要重復(fù)計(jì)算值。
7. useCallbck 用于緩存函數(shù),避免函數(shù)被重復(fù)創(chuàng)建,它是 useMemo 的語(yǔ)法糖。useCallback(fn, deps) 的效果相當(dāng)于是 useMemo(() => fn, deps)。
自定義 Hook 的使用
自定義 Hook 的命名規(guī)則是以 use 開(kāi)頭的函數(shù),比如 useLocalStorage 就符合自定義 Hook 的命名規(guī)范。 使用自定義 Hook 的場(chǎng)景有很多,如表單處理、動(dòng)畫、訂閱聲明、定時(shí)器等等可復(fù)用的邏輯都能通過(guò)自定義 Hook 來(lái)抽象實(shí)現(xiàn)。
在自定義 Hook 中,可以使用 Hooks 函數(shù)將可復(fù)用的邏輯和功能提取出來(lái),并將內(nèi)部的 state 或操作的方法從自定義 Hook 函數(shù)中返回出來(lái)。函數(shù)組件使用時(shí)就可以像調(diào)用普通函數(shù)一祥調(diào)用自定義 Hook 函數(shù), 并將自定義 Hook 返回的 state 和操作方法通過(guò)解構(gòu)保存到變量中。
下面是 useLocalStorage 的實(shí)現(xiàn),它將 state 同步到本地存儲(chǔ),以使其在頁(yè)面刷新后保持不變。 用法與 useState 相似,不同之處在于我們傳入了本地存儲(chǔ)鍵,以便我們可以在頁(yè)面加載時(shí)默認(rèn)為該值,而不是指定的初始值。
import { useState } from 'react';// Usage function App() {// Similar to useState but first arg is key to the value in local storage.const [name, setName] = useLocalStorage('name', 'Bob');return (<div><inputtype="text"placeholder="Enter your name"value={name}onChange={e => setName(e.target.value)}/></div>); }// Hook function useLocalStorage(key, initialValue) {// State to store our value// Pass initial state function to useState so logic is only executed onceconst [storedValue, setStoredValue] = useState(() => {try {// Get from local storage by keyconst item = window.localStorage.getItem(key);// Parse stored json or if none return initialValuereturn item ? JSON.parse(item) : initialValue;} catch (error) {// If error also return initialValueconsole.log(error);return initialValue;}});// Return a wrapped version of useState's setter function that ...// ... persists the new value to localStorage.const setValue = value => {try {// Allow value to be a function so we have same API as useStateconst valueToStore =value instanceof Function ? value(storedValue) : value;// Save statesetStoredValue(valueToStore);// Save to local storagewindow.localStorage.setItem(key, JSON.stringify(valueToStore));} catch (error) {// A more advanced implementation would handle the error caseconsole.log(error);}};return [storedValue, setValue]; }注意: 自定義 Hook 函數(shù)在定義時(shí),也可以使用另一個(gè)自定義 Hook 函數(shù)。
Hook 使用約束
class 組件與 Hook 之間的映射與轉(zhuǎn)換
函數(shù)組件相比 class 組件會(huì)缺少很多功能,但大多可以通過(guò) Hook 的方式來(lái)實(shí)現(xiàn)。
生命周期
- constructor:class 組件的構(gòu)造函數(shù)一般是用于初始化 state 數(shù)據(jù)或是給事件綁定 this 指向的。函數(shù)組件內(nèi)沒(méi)有 this 指向的問(wèn)題,因此可以忽略。而 state 可以通過(guò) useState/useReducer 來(lái)實(shí)現(xiàn)。
- getDerivedStateFromProps:getDerivedStateFromProps 一般用于在組件 props 發(fā)生變化時(shí)派生 state。Hooks 實(shí)現(xiàn)同等效果如下:
``` jsx function ScrollView({row}) { const [isScrollingDown, setIsScrollingDown] = useState(false); const [prevRow, setPrevRow] = useState(null);
function ScrollView({row}) {const [isScrollingDown, setIsScrollingDown] = useState(false);const [prevRow, setPrevRow] = useState(null);if (row !== prevRow) {// Row 自上次渲染以來(lái)發(fā)生過(guò)改變。更新 isScrollingDown。setIsScrollingDown(prevRow !== null && row > prevRow);setPrevRow(row);}return `Scrolling down: ${isScrollingDown}`; }- shouldComponentUpdate: 使用 React.memo 應(yīng)用到函數(shù)組件中后,當(dāng) props 發(fā)生變化時(shí),會(huì)對(duì) props 的新舊值進(jìn)行前對(duì)比,相當(dāng)于是 PureComponent 的功能。如果你還想自己定義比較函數(shù)的話,可以給 React.memo 的第二個(gè)參數(shù)傳一個(gè)函數(shù),若函數(shù)返回 true 則跳過(guò)更新。
- render: 函數(shù)組件本身就是一個(gè) render 函數(shù)。
- componentDidMount / componentDidUpdate / componentWillUnmount:
useEffect 第二個(gè)參數(shù)的依賴項(xiàng)為空時(shí),相當(dāng)于 componentDidMount,組件掛載后只會(huì)執(zhí)行一次。每個(gè) useEffect 返回的函數(shù)相當(dāng)于是 componentWillUnmount 同等效果的操作。若有依賴,則 effect 函數(shù)相當(dāng)于是 componentDidUpdate:
// 沒(méi)有依賴項(xiàng),僅執(zhí)行一次 useEffect(() => {const subscription = props.source.subscribe();// 相當(dāng)于 componentWillUnmountreturn () => {subscription.unsubscribe();}; }, []);// 若有依賴項(xiàng),相當(dāng)于 componentDidUpdate // 當(dāng) page 發(fā)生變化時(shí)會(huì)觸發(fā) effect 函數(shù) useEffect(() => {fetchList({ page }); }, [page]);Hooks 沒(méi)有實(shí)現(xiàn)的生命周期鉤子
- getSnapshotBeforeUpdate
- getDerivedStateFromError
- componentDidCatch
轉(zhuǎn)換實(shí)例變量
使用 useRef 設(shè)置可變數(shù)據(jù)。
強(qiáng)制更新 Hook 組件
設(shè)置一個(gè)沒(méi)有實(shí)際作用的 state,然后強(qiáng)制更新 state 的值觸發(fā)渲染。
const Todo = () => {// 使用 useState,用隨機(jī)數(shù)據(jù)更新也行const [ignored, forceUpdate] = useReducer(x => x + 1, 0);function handleClick() {forceUpdate();}return <button click={handleClick}>強(qiáng)制更新組件</button> }獲取舊的 props 和 state
可以通過(guò) useRef 來(lái)保存數(shù)據(jù),因?yàn)殇秩緯r(shí)不會(huì)覆蓋掉可變數(shù)據(jù)。
function Counter() {const [count, setCount] = useState(0);const prevCountRef = useRef();useEffect(() => {prevCountRef.current = count;}, []);const prevCount = prevCountRef.current;return <h1>Now: {count}, before: {prevCount}</h1>; }受控組件與非受控組件的區(qū)別
受控組件主要是指表單的值受到 state 的控制,它需要自行監(jiān)聽(tīng) onChange 事件來(lái)更新 state。
由于受控組件每次都要編寫事件處理器才能更新 state 數(shù)據(jù)、可能會(huì)有點(diǎn)麻煩,React 提供另一種代替方案是非受控組件。
非受控組件將真實(shí)數(shù)據(jù)儲(chǔ)存在 DOM 節(jié)點(diǎn)中,它可以為表單項(xiàng)設(shè)置默認(rèn)值,不需要手動(dòng)更新數(shù)據(jù)。當(dāng)需要用到表單數(shù)據(jù)時(shí)再通過(guò) ref 從 DOM 節(jié)點(diǎn)中取出數(shù)據(jù)即可。
注意: 多數(shù)情況下React 推薦編寫受控組件。
擴(kuò)展資料: 受控和非受控制使用場(chǎng)景的選擇
Portals 是什么?
Portals 就像個(gè)傳送門,它可以將子節(jié)點(diǎn)渲染到存在于父組件以外的 DOM 節(jié)點(diǎn)的方案。
比如 Dialog 是一個(gè)全局組件,按照傳統(tǒng)渲染組件的方式,Dialog 可能會(huì)受到其容器 css 的影響。因此可以使用 Portals 讓組件在視覺(jué)上渲染到 <body> 中,使其樣式不受 overflow: hidden 或 z-index 的影響。
- 下一篇文章: React 面試指南 (下)
- 原文出自: React 知識(shí)回顧 (使用篇) | Anran758's blog
- 前端面試筆記: front-end-lab
總結(jié)
以上是生活随笔為你收集整理的react取消捕获_React 面试指南 (上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pano2vr怎么制作漫游_春节7天长假
- 下一篇: kettle使用数据库来生成序列_Pyt