一裂允、react 和 vue 的區(qū)別是什么绝编?
1十饥、vue是響應(yīng)式的數(shù)據(jù)雙向綁定系統(tǒng)祖乳,而react是單向數(shù)據(jù)流逗堵,沒有雙向綁定。
2眷昆、vue的語法較為簡單蜒秤,適用于小型項(xiàng)目創(chuàng)建,而react更適用于Web端和原生App的開發(fā)亚斋,側(cè)重于大型應(yīng)用作媚。
3帅刊、Templating vs JSX
React和Vue.js之間最大的區(qū)別在于模板的實(shí)現(xiàn)方式纸泡。
4、狀態(tài)管理與對象屬性
react:
如果你熟悉React赖瞒,你就會知道應(yīng)用狀態(tài)是一個關(guān)鍵概念女揭。甚至還有一些專門用于管理大型狀態(tài)對象的框架,比如Redux冒黑。另外,React應(yīng)用程序中的狀態(tài)數(shù)據(jù)是不可變的勤哗,這意味著它不能直接更改(盡管這并不完全正確)抡爹。在React中,你需要使用setState()方法(或useState()鉤子)來修改本地狀態(tài)中的任何內(nèi)容芒划。
vue:
對于Vue.js冬竟,不需要本地狀態(tài)對象,數(shù)據(jù)是通過Vue對象上的data屬性管理的民逼。
在Vue中泵殴,不需要調(diào)用像setState()這樣的狀態(tài)管理函數(shù),因?yàn)閂ue對象上的data參數(shù)充當(dāng)了應(yīng)用程序數(shù)據(jù)的持有者拼苍。
在關(guān)于大規(guī)模應(yīng)用程序的狀態(tài)管理的話題上笑诅,Vue.js的創(chuàng)建者Evan You說過,這種解決方案適合小規(guī)模應(yīng)用程序,但不能擴(kuò)展到大型應(yīng)用程序吆你。
在大多數(shù)情況下弦叶,框架本身提供的內(nèi)置狀態(tài)管理模式對于大型應(yīng)用程序是不夠的,必須使用像Redux或Vuex這樣的專用解決方案妇多。
5伤哺、Build Tools
在React中,這是Create React App(CRA)者祖;
在Vue.js中立莉,它是vue-cli。
6.這兩個框架之間的最后一個相似之處(和不同之處)是它們?nèi)绾翁幚戆樯蚣堋?/h6>
React和Vue.js都只關(guān)注UI層七问,而把路由和狀態(tài)處理等功能留給其他框架蜓耻。
Vue.js和React之間的區(qū)別在于它們?nèi)绾闻c各自的配套框架相關(guān)聯(lián)。
Vue.js核心團(tuán)隊(duì)維護(hù)Vue -router和Vue框架烂瘫,并將它們置于主Vue之下媒熊。
React -router和React -redux由社區(qū)成員維護(hù),并不是在Facebook/React的官方保護(hù)傘下坟比。
二芦鳍、虛擬DOM的原理?優(yōu)點(diǎn)與缺點(diǎn)葛账?
原理:
1.虛擬DOM本質(zhì)上是JavaScript對象,是對真實(shí)DOM的抽象
2.狀態(tài)變更時(shí)柠衅,記錄新樹和舊樹的差異
3.最后把差異更新到真正的dom中
優(yōu)點(diǎn):
1.保證性能下限: 虛擬DOM可以經(jīng)過diff找出最小差異,然后批量進(jìn)行patch,這種操作雖然比不上手動優(yōu)化,但是比起粗暴的DOM操作性能要好很多,因此虛擬DOM可以保證性能下限
無需手動操作DOM: 虛擬DOM的diff和patch都是在一次更新中自動進(jìn)行的,我們無需手動操作DOM,極大提高開發(fā)效率
2.跨平臺: 虛擬DOM本質(zhì)上是JavaScript對象,而DOM與平臺強(qiáng)相關(guān),相比之下虛擬DOM可以進(jìn)行更方便地跨平臺操作,例如服務(wù)器渲染、移動端開發(fā)等等
缺點(diǎn):
無法進(jìn)行極致優(yōu)化: 在一些性能要求極高的應(yīng)用中虛擬DOM無法進(jìn)行針對性的極致優(yōu)化,比如VScode采用直接手動操作DOM的方式進(jìn)行極端的性能優(yōu)化
三籍琳、類組件和函數(shù)組件之間的區(qū)別是菲宴?
類組件:可以使用其他特性,如狀態(tài) state 和生命周期鉤子
函數(shù)組件:當(dāng)組件只是接收 props 渲染到頁面時(shí)趋急,就是無狀態(tài)組件喝峦,也被稱為啞組件或展示組件。
區(qū)別:
1.類組件有 this呜达,函數(shù)組件沒有
2.類組件有生命周期谣蠢,函數(shù)組件沒有
3.類組件有狀態(tài) state,函數(shù)組件沒有
函數(shù)組件的性能比類組件的性能要高查近,因?yàn)轭惤M件使用的時(shí)候要實(shí)例化眉踱,而函數(shù)組件直接執(zhí)行函數(shù)取返回結(jié)果即可。為了提高性能霜威,盡量使用函數(shù)組件谈喳。
四、React 中 refs 是做什么的戈泼?
Refs 提供了一種訪問在render方法中創(chuàng)建的 DOM 節(jié)點(diǎn)或者 React 元素的方法婿禽。在典型的數(shù)據(jù)流中赏僧,props 是父子組件交互的唯一方式,想要修改子組件谈宛,需要使用新的pros重新渲染它次哈。凡事有例外,某些情況下咱們需要在典型數(shù)據(jù)流外吆录,強(qiáng)制修改子代窑滞,這個時(shí)候可以使用 Refs。
咱們可以在組件添加一個 ref 屬性來使用恢筝,該屬性的值是一個回調(diào)函數(shù)哀卫,接收作為其第一個參數(shù)的底層 DOM 元素或組件的掛載實(shí)例。
class UnControlledForm extends Component {
handleSubmit = () => {
console.log("Input Value: ", this.input.value)
}
render () {
return (
<form onSubmit={this.handleSubmit}>
<input
type='text'
ref={(input) => this.input = input} />
<button type='submit'>Submit</button>
</form>
)
}
}
五撬槽、state 和 props 區(qū)別是什么此改?
props和state是普通的 JS 對象。雖然它們都包含影響渲染輸出的信息侄柔,但是它們在組件方面的功能是不同的共啃。即
1.state 是組件自己管理數(shù)據(jù),控制自己的狀態(tài)暂题,可變移剪;
2.props 是外部傳入的數(shù)據(jù)參數(shù),不可變薪者;
3.沒有state的叫做無狀態(tài)組件(函數(shù)組件)纵苛,有state的叫做有狀態(tài)組件;
4.多用 props言津,少用 state攻人,也就是多寫無狀態(tài)組件(因?yàn)轭惤M件使用的時(shí)候要實(shí)例化,而函數(shù)組件直接執(zhí)行函數(shù)取返回結(jié)果即可悬槽。為了提高性能怀吻,盡量使用函數(shù)組件。)初婆。
六蓬坡、什么是高階組件?
高階組件(HOC)是接受一個組件并返回一個新組件的函數(shù)烟逊。高階組件不是組件渣窜,是增強(qiáng)函數(shù)铺根,可以輸入一個元組件宪躯,返回出一個新的增強(qiáng)組件
const EnhancedComponent = higherOrderComponent(WrappedComponent);
HOC 可以用于:
1.代碼重用、邏輯和引導(dǎo)抽象
2.渲染劫持
3.state 抽象和操作
4.props 處理
七位迂、在構(gòu)造函數(shù)調(diào)用 super 并將 props 作為參數(shù)傳入的作用是啥访雪?详瑞?
傳遞 props
class MyComponent extends React.Component {
constructor(props) {
super(props);
console.log(this.props); // { name: 'sudheer',age: 30 }
}
}
沒傳遞props
class MyComponent extends React.Component {
constructor(props) {
super();
console.log(this.props); // undefined
// 但是 Props 參數(shù)仍然可用
console.log(props); // Prints { name: 'sudheer',age: 30 }
}
render() {
// 構(gòu)造函數(shù)外部不受影響
console.log(this.props) // { name: 'sudheer',age: 30 }
}
}
上面示例揭示了一點(diǎn)。props 的行為只有在構(gòu)造函數(shù)中是不同的臣缀,在構(gòu)造函數(shù)之外也是一樣的坝橡。
八、講講什么是 JSX 精置?
JSX是javascript的語法擴(kuò)展计寇。它就像一個擁有javascript全部功能的模板語言。它生成React元素脂倦,這些元素將在DOM中呈現(xiàn)番宁。React建議在組件使用JSX。在JSX中赖阻,我們結(jié)合了javascript和HTML蝶押,并生成了可以在DOM中呈現(xiàn)的react元素。
JSX 代碼本身不能被瀏覽器讀取火欧,必須使用Babel和webpack等工具將其轉(zhuǎn)換為傳統(tǒng)的JS
class MyComponent extends React.Component {
render() {
let props = this.props;
return (
<div className="my-component">
<a href={props.url}>{props.name}</a>
</div>
);
}
}
九棋电、為什么不能直接更新 state 呢 ?
如果試圖直接更新 state ,則不會重新渲染組件苇侵。
// 錯誤
This.state.message = 'Hello world';
需要使用setState()方法來更新 state赶盔。它調(diào)度對組件state對象的更新。當(dāng)state改變時(shí)衅檀,組件通過重新渲染來響應(yīng):
// 正確做法
This.setState({message: ‘Hello World’});
十招刨、React 組件生命周期有哪些不同階段?
1.Initialization:
在這個階段哀军,組件準(zhǔn)備設(shè)置初始化狀態(tài)和默認(rèn)屬性沉眶。
2.Mounting:
react 組件已經(jīng)準(zhǔn)備好掛載到瀏覽器 DOM 中。這個階段包括componentWillMount和componentDidMount生命周期方法杉适。
3.Updating:
在這個階段谎倔,組件以兩種方式更新,發(fā)送新的 props 和 state 狀態(tài)猿推。此階段包括shouldComponentUpdate片习、componentWillUpdate和componentDidUpdate生命周期方法。
4.Unmounting:
在這個階段蹬叭,組件已經(jīng)不再被需要了藕咏,它從瀏覽器 DOM 中卸載下來。這個階段包含 componentWillUnmount 生命周期方法秽五。
除以上四個常用生命周期外孽查,還有一個錯誤處理的階段:
Error Handling:在這個階段,不論在渲染的過程中坦喘,還是在生命周期方法中或是在任何子組件的構(gòu)造函數(shù)中發(fā)生錯誤盲再,該組件都會被調(diào)用西设。這個階段包含了 componentDidCatch 生命周期方法。
十一答朋、React 組件的生命周期方法贷揽?
componentWillMount() – 在渲染之前執(zhí)行,在客戶端和服務(wù)器端都會執(zhí)行梦碗。
componentDidMount() – 僅在第一次渲染后在客戶端執(zhí)行禽绪。
componentWillReceiveProps() – 當(dāng)從父類接收到 props 并且在調(diào)用另一個渲染器之前調(diào)用。
shouldComponentUpdate() – 根據(jù)特定條件返回 true 或 false洪规。如果你希望更新組件丐一,請返回true 否則返回 false。默認(rèn)情況下淹冰,它返回 false库车。
componentWillUpdate() – 在 DOM 中進(jìn)行渲染之前調(diào)用。
componentDidUpdate() – 在渲染發(fā)生后立即調(diào)用樱拴。
componentWillUnmount() – 從 DOM 卸載組件后調(diào)用柠衍。用于清理內(nèi)存空間。
十二晶乔、什么是 prop drilling珍坊,如何避免?
是什么:在構(gòu)建 React 應(yīng)用程序時(shí)正罢,在多層嵌套組件來使用另一個嵌套組件提供的數(shù)據(jù)阵漏。最簡單的方法是將一個 prop 從每個組件一層層的傳遞下去,從源組件傳遞到深層嵌套組件翻具,這叫做prop drilling履怯。
prop drilling的主要缺點(diǎn)是原本不需要數(shù)據(jù)的組件變得不必要地復(fù)雜,并且難以維護(hù)裆泳。
如何避免:使用React Context叹洲。通過定義提供數(shù)據(jù)的Provider組件,并允許嵌套的組件通過Consumer組件或useContext Hook 使用上下文數(shù)據(jù)工禾。
十三运提、什么是 React Context?
Context 通過組件樹提供了一個傳遞數(shù)據(jù)的方法,從而避免了在每一個層級手動的傳遞 props 屬性闻葵。
十四民泵、什么是純函數(shù)?
純函數(shù)始終在給定相同參數(shù)的情況下返回相同結(jié)果槽畔。
十五栈妆、當(dāng)調(diào)用setState時(shí),React render 是如何工作的?
將"render"分為兩個步驟:
1.虛擬 DOM 渲染:
當(dāng)render方法被調(diào)用時(shí)签钩,它返回一個新的組件的虛擬 DOM 結(jié)構(gòu)。當(dāng)調(diào)用setState()時(shí)坏快,render會被再次調(diào)用铅檩,因?yàn)槟J(rèn)情況下shouldComponentUpdate總是返回true,所以默認(rèn)情況下 React 是沒有優(yōu)化的莽鸿。
2.原生 DOM 渲染:
React 只會在虛擬DOM中修改真實(shí)DOM節(jié)點(diǎn)昧旨,而且修改的次數(shù)非常少——這是很棒的React特性,它優(yōu)化了真實(shí)DOM的變化祥得,使React變得更快兔沃。
十六、React的請求應(yīng)該放在哪個生命周期中?
目前官方推薦的異步請求是在componentDidmount中進(jìn)行.
如果有特殊需求需要提前請求,也可以在特殊情況下在constructor中請求:
十七级及、setState到底是異步還是同步?
先給出答案: 有時(shí)表現(xiàn)出異步,有時(shí)表現(xiàn)出同步
1.setState只在合成事件和鉤子函數(shù)中是“異步”的乒疏,在原生事件和setTimeout 中都是同步的。
2.setState 的“異步”并不是說內(nèi)部由異步代碼實(shí)現(xiàn)饮焦,其實(shí)本身執(zhí)行的過程和代碼都是同步的怕吴,只是合成事件和鉤子函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在合成事件和鉤子函數(shù)中沒法立馬拿到更新后的值县踢,形成了所謂的“異步”转绷,當(dāng)然可以通過第二個參數(shù) setState(partialState, callback) 中的callback拿到更新后的結(jié)果。
3.setState 的批量更新優(yōu)化也是建立在“異步”(合成事件硼啤、鉤子函數(shù))之上的议经,在原生事件和setTimeout 中不會批量更新,在“異步”中如果對同一個值進(jìn)行多次setState谴返,setState的批量更新策略會對其進(jìn)行覆蓋煞肾,取最后一次的執(zhí)行,如果是同時(shí)setState多個不同的值嗓袱,在更新時(shí)會對其進(jìn)行合并批量更新扯旷。
十八、React組件通信如何實(shí)現(xiàn)?
React組件間通信方式:
1.父組件向子組件通訊:
父組件可以向子組件通過傳 props 的方式索抓,向子組件進(jìn)行通訊
2.子組件向父組件通訊:
props+回調(diào)的方式,父組件向子組件傳遞props進(jìn)行通訊钧忽,此props為作用域?yàn)楦附M件自身的函數(shù),子組件調(diào)用該函數(shù)逼肯,將子組件想要傳遞的信息耸黑,作為參數(shù),傳遞到父組件的作用域中
3.兄弟組件通信:
找到這兩個兄弟節(jié)點(diǎn)共同的父節(jié)點(diǎn),結(jié)合上面兩種方式由父節(jié)點(diǎn)轉(zhuǎn)發(fā)信息進(jìn)行通信
4.跨層級通信:
Context設(shè)計(jì)目的是為了共享那些對于一個組件樹而言是“全局”的數(shù)據(jù)篮幢,例如當(dāng)前認(rèn)證的用戶大刊、主題或首選語言,對于跨越多層的全局?jǐn)?shù)據(jù)通過Context通信再適合不過
5.發(fā)布訂閱模式:
發(fā)布者發(fā)布事件,訂閱者監(jiān)聽事件并做出反應(yīng),我們可以通過引入event模塊進(jìn)行通信
6.全局狀態(tài)管理工具:
借助Redux或者M(jìn)obx等全局狀態(tài)管理工具進(jìn)行通信,這種工具會維護(hù)一個全局狀態(tài)中心Store,并根據(jù)不同的事件產(chǎn)生新的狀態(tài)
十九三椿、React如何進(jìn)行組件/邏輯復(fù)用?
拋開已經(jīng)被官方棄用的Mixin,組件抽象的技術(shù)目前有三種比較主流:
1.高階組件:
屬性代理
反向繼承
2.渲染屬性
3.react-hooks
二十缺菌、mixin葫辐、hoc、render props伴郁、react-hooks的優(yōu)劣如何耿战?
Mixin的缺陷:
組件與 Mixin 之間存在隱式依賴(Mixin 經(jīng)常依賴組件的特定方法,但在定義組件時(shí)并不知道這種依賴關(guān)系)
多個 Mixin 之間可能產(chǎn)生沖突(比如定義了相同的state字段)
Mixin 傾向于增加更多狀態(tài)焊傅,這降低了應(yīng)用的可預(yù)測性(The more state in your application, the harder it is to reason about it.)剂陡,導(dǎo)致復(fù)雜度劇增
-
隱式依賴導(dǎo)致依賴關(guān)系不透明,維護(hù)成本和理解成本迅速攀升:
難以快速理解組件行為狐胎,需要全盤了解所有依賴 Mixin 的擴(kuò)展行為鸭栖,及其之間的相互影響
組價(jià)自身的方法和state字段不敢輕易刪改,因?yàn)殡y以確定有沒有 Mixin 依賴它
Mixin 也難以維護(hù)握巢,因?yàn)?Mixin 邏輯最后會被打平合并到一起晕鹊,很難搞清楚一個 Mixin 的輸入輸出
HOC相比Mixin的優(yōu)勢:
- HOC通過外層組件通過 Props 影響內(nèi)層組件的狀態(tài),而不是直接改變其 State不存在沖突和互相干擾,這就降低了耦合度
- 不同于 Mixin 的打平+合并暴浦,HOC 具有天然的層級結(jié)構(gòu)(組件樹結(jié)構(gòu))捏题,這又降低了復(fù)雜度
HOC的缺陷:
- 擴(kuò)展性限制: HOC 無法從外部訪問子組件的 State因此無法通過shouldComponentUpdate濾掉不必要的更新,React 在支持 ES6 Class 之后提供了React.PureComponent來解決這個問題
- Ref 傳遞問題: Ref 被隔斷,后來的React.forwardRef 來解決這個問題
- Wrapper Hell: HOC可能出現(xiàn)多層包裹組件的情況,多層抽象同樣增加了復(fù)雜度和理解成本
- 命名沖突: 如果高階組件多次嵌套,沒有使用命名空間的話會產(chǎn)生沖突,然后覆蓋老屬性
- 不可見性: HOC相當(dāng)于在原有組件外層再包裝一個組件,你壓根不知道外層的包裝是啥,對于你是黑盒
Render Props優(yōu)點(diǎn):
- 上述HOC的缺點(diǎn)Render Props都可以解決
Render Props缺陷:
- 使用繁瑣: HOC使用只需要借助裝飾器語法通常一行代碼就可以進(jìn)行復(fù)用,Render Props無法做到如此簡單
- 嵌套過深: Render Props雖然擺脫了組件多層嵌套的問題,但是轉(zhuǎn)化為了函數(shù)回調(diào)的嵌套
React Hooks優(yōu)點(diǎn):
- 簡潔: React Hooks解決了HOC和Render Props的嵌套問題,更加簡潔
- 解耦: React Hooks可以更方便地把 UI 和狀態(tài)分離,做到更徹底的解耦
- 組合: Hooks 中可以引用另外的 Hooks形成新的Hooks,組合變化萬千
- 函數(shù)友好: React Hooks為函數(shù)組件而生,從而解決了類組件的幾大問題:
- this 指向容易錯誤
- 分割在不同聲明周期中的邏輯使得代碼難以理解和維護(hù)
- 代碼復(fù)用成本高(高階組件容易使代碼量劇增)
React Hooks缺陷:
額外的學(xué)習(xí)成本(Functional Component 與 Class Component 之間的困惑)
寫法上有限制(不能出現(xiàn)在條件、循環(huán)中)肉渴,并且寫法限制增加了重構(gòu)成本
破壞了PureComponent公荧、React.memo淺比較的性能優(yōu)化效果(為了取最新的props和state,每次render()都要重新創(chuàng)建事件處函數(shù))
在閉包場景可能會引用到舊的state同规、props值
內(nèi)部實(shí)現(xiàn)上不直觀(依賴一份可變的全局狀態(tài)循狰,不再那么“純”)
React.memo并不能完全替代shouldComponentUpdate(因?yàn)槟貌坏?state change,只針對 props change)
二十一券勺、redux的工作流程?
Store:
保存數(shù)據(jù)的地方绪钥,你可以把它看成一個容器,整個應(yīng)用只能有一個Store关炼。
State:
Store對象包含所有數(shù)據(jù)程腹,如果想得到某個時(shí)點(diǎn)的數(shù)據(jù),就要對Store生成快照儒拂,這種時(shí)點(diǎn)的數(shù)據(jù)集合寸潦,就叫做State。
Action:
State的變化社痛,會導(dǎo)致View的變化见转。但是,用戶接觸不到State蒜哀,只能接觸到View斩箫。所以,State的變化必須是View導(dǎo)致的。Action就是View發(fā)出的通知乘客,表示State應(yīng)該要發(fā)生變化了狐血。
Action Creator:
View要發(fā)送多少種消息,就會有多少種Action易核。如果都手寫匈织,會很麻煩,所以我們定義一個函數(shù)來生成Action耸成,這個函數(shù)就叫Action Creator。
Reducer:
Store收到Action以后浴鸿,必須給出一個新的State井氢,這樣View才會發(fā)生變化。這種State的計(jì)算過程就叫做Reducer岳链。Reducer是一個函數(shù)花竞,它接受Action和當(dāng)前State作為參數(shù),返回一個新的State掸哑。
dispatch:
是View發(fā)出Action的唯一方法约急。
然后我們過下整個工作流程:
首先,用戶(通過View)發(fā)出Action苗分,發(fā)出方式就用到了dispatch方法厌蔽。
然后,Store自動調(diào)用Reducer摔癣,并且傳入兩個參數(shù):當(dāng)前State和收到的Action奴饮,Reducer會返回新的State
State一旦有變化,Store就會調(diào)用監(jiān)聽函數(shù)择浊,來更新View戴卜。
到這兒為止,一次用戶交互流程結(jié)束琢岩⊥栋可以看到,在整個流程中數(shù)據(jù)都是單向流動的担孔,這種方式保證了流程的清晰江锨。
二十二、Hook有哪些優(yōu)勢?
1.減少狀態(tài)邏輯復(fù)用的風(fēng)險(xiǎn)
Hook和 Mixin在用法上有一定的相似之處,但是 Mixin引入的邏輯和狀態(tài)是可以相互覆蓋的斟冕,而多個 Hook之間互不影響溶其,這讓我們不需要在把一部分精力放在防止避免邏輯復(fù)用的沖突上。在不遵守約定的情況下使用 HOC也有可能帶來一定沖突哨啃,比如 props覆蓋等等割粮,使用 Hook則可以避免這些問題争便。
2.避免地獄式嵌套
大量使用 HOC的情況下讓我們的代碼變得嵌套層級非常深浮毯,使用 HOC完疫,我們可以實(shí)現(xiàn)扁平式的狀態(tài)邏輯復(fù)用,而避免了大量的組件嵌套债蓝。
3.讓組件更容易理解
在使用 class組件構(gòu)建我們的程序時(shí)壳鹤,他們各自擁有自己的狀態(tài),業(yè)務(wù)邏輯的復(fù)雜使這些組件變得越來越龐大饰迹,各個生命周期中會調(diào)用越來越多的邏輯芳誓,越來越難以維護(hù)。使用 Hook啊鸭,可以讓你更大限度的將公用邏輯抽離锹淌,將一個組件分割成更小的函數(shù),而不是強(qiáng)制基于生命周期方法進(jìn)行分割赠制。
4.使用函數(shù)代替class
相比函數(shù)赂摆,編寫一個 class可能需要掌握更多的知識,需要注意的點(diǎn)也越多钟些,比如 this指向烟号、綁定事件等等。另外政恍,計(jì)算機(jī)理解一個 class比理解一個函數(shù)更快汪拥。Hooks讓你可以在 classes之外使用更多 React的新特性。