react/vue常見(jiàn)問(wèn)題整理

一疚俱、react

1. react生命周期

react 15生命周期.png
react 16生命周期.png

react 16生命周期相對(duì)于15的變化:
componentWillMount,componentWillReceiveProps, componentWillUpdate準(zhǔn)備廢除腹缩。理由:主要是16 版本 render 之前的生命周期可能會(huì)被多次執(zhí)行岖赋。
static getDerivedStateFromProps和 getSnapshotBeforeUpdate新增,用于補(bǔ)充上述的生命周期柴灯。

2. 對(duì)虛擬dom的理解

本質(zhì)上是 JavaScript 對(duì)象物延,這個(gè)對(duì)象就是更加輕量級(jí)的對(duì) DOM 的描述宣旱。DOM 有很多屬性,如果把對(duì) DOM 的 diff 操作轉(zhuǎn)移到 JS 對(duì)象叛薯,就可以避免大量對(duì) DOM 的查詢(xún)操作浑吟。這個(gè)更輕量級(jí)的 JS 對(duì)象就稱(chēng)為 Virtual DOM 。

虛擬dom工作過(guò)程:

  1. 維護(hù)一個(gè)使用 JS 對(duì)象表示的 Virtual DOM耗溜,與真實(shí) DOM 一一對(duì)應(yīng)
  2. 對(duì)前后兩個(gè) Virtual DOM 做 diff 组力,生成變更(Mutation)
  3. 把變更應(yīng)用于真實(shí) DOM,生成最新的真實(shí) DOM

可以看出抖拴,因?yàn)橐炎兏鼞?yīng)用到真實(shí) DOM 上忿项,所以還是避免不了要直接操作 DOM ,但是 React 的 diff 算法會(huì)把 DOM 改動(dòng)次數(shù)降到最低城舞。
diff的原理:將樹(shù)形結(jié)構(gòu)按照層級(jí)分解,只比較同級(jí)元素寞酿;給列表結(jié)構(gòu)每一個(gè)單元添加key屬性家夺,方便比較。

3. setState

如果直接修改state伐弹,react無(wú)法得知需要重新渲染組件拉馋,使用setState(),react可以更新組件UI。調(diào)用setState后煌茴,react將傳入的參數(shù)與當(dāng)前狀態(tài)合并随闺,生成新的元素樹(shù),與老的元素樹(shù)進(jìn)行對(duì)比蔓腐,根據(jù)差異對(duì)界面進(jìn)行最小化重新渲染矩乐。
State 的更新可能是異步的,所以如果setState需要要依賴(lài)this.state或this.props的值回论,需傳入函數(shù)散罕。
出于性能考慮,React 可能會(huì)把多個(gè) setState() 調(diào)用合并成一個(gè)調(diào)用(render)傀蓉。setState不會(huì)立即改變state的值欧漱,在 React的生命周期和合成事件中, React仍然處于他的更新機(jī)制中葬燎,這時(shí)無(wú)論調(diào)用多少次 setState误甚,都不會(huì)立即執(zhí)行更新,而是將其放入一個(gè)任務(wù)隊(duì)列谱净。當(dāng)上一次更新機(jī)制執(zhí)行完畢(eg窑邦;生命周期),將多個(gè)setState合并岳遥,一次性渲染頁(yè)面奕翔。
通過(guò) addEventListener || setTimeout/setInterval 的方式處理的setState會(huì)同步更新。

4. react的事件機(jī)制

react事件沒(méi)有綁定在真實(shí)的dom上浩蓉,而是通過(guò)事件代理派继,綁在document上,對(duì)事件進(jìn)行分發(fā)捻艳。React的所有事件都通過(guò) document進(jìn)行統(tǒng)一分發(fā)驾窟。當(dāng)真實(shí) Dom觸發(fā)事件后冒泡到 document后才會(huì)對(duì) React事件進(jìn)行處理。
react事件要自己綁定this认轨,因?yàn)槭录壎ㄔ赿ocument上绅络,不是真實(shí)要調(diào)用的組件上。
react事件和原生事件區(qū)別:

  1. react事件命名為駝峰式嘁字,不是全小寫(xiě)恩急;
  2. jsx可以傳遞一個(gè)函數(shù)為事件處理程序,不是字符串
  3. react中不能返回false阻止默認(rèn)事件纪蜒,必須調(diào)用preventDefault衷恭。

合成事件:事件處理函數(shù)的參數(shù)。事件處理程序?qū)鬟f SyntheticEvent 的實(shí)例纯续,這是一個(gè)跨瀏覽器原生事件包裝器随珠。它具有與瀏覽器原生事件相同的接口灭袁。
因?yàn)檎鎸?shí)dom出發(fā)時(shí)間冒泡到document后才會(huì)處理react事件,所以事件觸發(fā)順序?yàn)椋?strong>原生事件 =》 合成事件 =》react真正在document上掛載的事件

react事件和原生事件最好不要混用窗看。因?yàn)樵录绻麍?zhí)行了stopPropagation方法茸歧,所有元素的事件都無(wú)法冒泡到document上,所有的react事件都無(wú)法觸發(fā)显沈。

5. refs

Refs是react提供的用來(lái)訪(fǎng)問(wèn)dom或者組件的句柄软瞎。是父組件用來(lái)獲取子組件的dom元素的。我們可以為元素添加 ref 屬性然后在回調(diào)函數(shù)中接受該元素在 DOM 樹(shù)中的句柄构罗,該值會(huì)作為回調(diào)函數(shù)的第一個(gè)參數(shù)返回铜涉。

  1. ref設(shè)置為普通字符串
    <button ref="myBtn"></button>
    給元素/組件定義ref屬性,后續(xù)可以通過(guò) this.refs.myBtn 來(lái)獲取這個(gè)真實(shí)DOM對(duì)象/組件的實(shí)例對(duì)象
  2. ref設(shè)置為回調(diào)函數(shù)
    <button ref={(sl)=> { this.myBtn = sl } }></button>
    給元素/組件定義ref屬性遂唧,后續(xù)可以通過(guò) this.myBtn 來(lái)獲取這個(gè)真實(shí)DOM對(duì)象/組件的實(shí)例對(duì)象
  • refs 并不是類(lèi)組件的專(zhuān)屬芙代,函數(shù)式組件同樣能夠利用閉包暫存其值。
function CustomForm ({handleSubmit}) {
  let inputElement
  return (
    <form onSubmit={() => handleSubmit(inputElement.value)}>
      <input
        type='text'
        ref={(input) => inputElement = input} />
      <button type='submit'>Submit</button>
    </form>
  )
}

6. 動(dòng)態(tài)加載

const LazyComponent = React.lazy(() =>
  import(/* webpackChunkName: 'lazyComponent'*/ "../components/LazyComponent")
);

7. Hook

hook之前的函數(shù)組件是無(wú)狀態(tài)盖彭、無(wú)副作用纹烹,只作單純的展示組件。
Hook 是一些可以讓你在函數(shù)組件里“鉤入” React state 及生命周期等特性的函數(shù)召边。
用法: useState, useEffect铺呵,useReducer,自定義hook

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  //定義一個(gè)state:isOnline隧熙,和修改state的方法setIsOnline
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  //副作用片挂,相當(dāng)于 componentDidMount 和 componentDidUpdate,頁(yè)面每次渲染都會(huì)執(zhí)行
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    //return一個(gè)方法就是清楚副作用贞盯,相當(dāng)于componentWillUnmount
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  //useEffect也可以傳入第二個(gè)參數(shù)[isOnline],代表只有isOnline修改時(shí)才執(zhí)行副作用
  //若第二個(gè)參數(shù)為 [],代表只有頁(yè)面第一次渲染執(zhí)行副作用

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

8. 受控組件和非受控組件

受控組件:使用表單元素時(shí)音念,將react的state作為數(shù)據(jù)的唯一源,并且控制著用戶(hù)輸入時(shí)表單發(fā)生的操作躏敢。被react以這種方式控制取值的表單元素就是受控組件闷愤。
非受控組件:表單數(shù)據(jù)由dom節(jié)點(diǎn)處理。

//受控組件
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleChange(event) {
    this.setState({value: event.target.value});
  }
  handleSubmit(event) {
    alert('提交的名字: ' + this.state.value);
    event.preventDefault();
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          名字:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="提交" />
      </form>
    );
  }
}
//非受控組件
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.input = React.createRef();
  }
  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.current.value);
    event.preventDefault();
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={this.input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

9. 高階組件(HOC)

高階組件(HOC)是參數(shù)為組件件余,返回值為新組件的函數(shù)讥脐。

二、vue

1. vue2.x的響應(yīng)式原理

vue初始化數(shù)據(jù)時(shí)啼器,用Object.defineProperty()將data中的property轉(zhuǎn)為getter/setter旬渠。每個(gè)vue實(shí)例對(duì)應(yīng)一個(gè)watcher實(shí)例,它在組件渲染過(guò)程中將所有property記錄為依賴(lài)端壳。當(dāng)屬性發(fā)生變化時(shí)觸發(fā)依賴(lài)項(xiàng)的setter坟漱,通知watcher,使對(duì)應(yīng)組件重新渲染更哄。
Vue3.x改用Proxy替代Object.defineProperty芋齿。

2. vue2.x中如何監(jiān)測(cè)數(shù)組變化

使用函數(shù)劫持的方法,對(duì)data中的數(shù)組進(jìn)行方法重寫(xiě)成翩,使其能夠通知依賴(lài)變更觅捆,如果數(shù)組中包含引用類(lèi)型,使用遞歸遍歷進(jìn)行監(jiān)控麻敌。

3. nextTick

在下次dom更新后執(zhí)行回調(diào)栅炒。nextTick主要使用了宏任務(wù)和微任務(wù),根據(jù)執(zhí)行環(huán)境嘗試采用Promise术羔,MutationObserver赢赊,setImmediate和setTimeout。

4. 生命周期

beforeCreated, created, beforeMounted, mounted, beforeDestroyed, destroyed

5. computed 和 watch

computed是一個(gè)計(jì)算屬性级历,基于響應(yīng)式依賴(lài)進(jìn)行緩存释移,適用于比較消耗性能的計(jì)算場(chǎng)景。很長(zhǎng)很復(fù)雜的表達(dá)式放在模板難以維護(hù)寥殖,就放入計(jì)算屬性玩讳。
watch是一個(gè)偵聽(tīng)器,監(jiān)聽(tīng)依賴(lài)變化來(lái)執(zhí)行一些操作嚼贡。

6. v-if 和 v-show

v-if在條件成立時(shí)才會(huì)渲染熏纯。提升頁(yè)面初始渲染性能。
v-show頁(yè)面渲染時(shí)就會(huì)同時(shí)渲染粤策,只是將display設(shè)為none樟澜,不展示。提升頁(yè)面多次切換渲染性能叮盘。

7. 組件中的data為什么是一個(gè)函數(shù)

一個(gè)組件被多次使用就是創(chuàng)建了多個(gè)實(shí)例秩贰,這些實(shí)例用的都是同一個(gè)構(gòu)造函數(shù),如果data是對(duì)象熊户,多個(gè)實(shí)例共享data的引用萍膛,數(shù)據(jù)會(huì)互相影響,使用函數(shù)可以避免這個(gè)問(wèn)題嚷堡。

8. vue模板編譯原理

vue的模板通常被編譯成了render函數(shù)蝗罗。會(huì)經(jīng)歷以下階段:

  • AST語(yǔ)法樹(shù)
  • 優(yōu)化
  • codegen

首先解析模板,轉(zhuǎn)化為AST語(yǔ)法樹(shù)蝌戒。使用正則表達(dá)式解析模板串塑,遇到標(biāo)簽,文本都會(huì)有相應(yīng)的鉤子進(jìn)行處理北苟。
模板中有很多數(shù)據(jù)不是響應(yīng)式的桩匪,首次渲染后不會(huì)再發(fā)生變化。優(yōu)化過(guò)程就是深度遍歷AST語(yǔ)法樹(shù)友鼻,將其標(biāo)記為靜態(tài)節(jié)點(diǎn)傻昙,用來(lái)跳過(guò)對(duì)他們的比對(duì)闺骚。
將優(yōu)化后的AST語(yǔ)法樹(shù)轉(zhuǎn)換為可執(zhí)行的代碼。

9. key

key是在使用v-for的列表中為節(jié)點(diǎn)添加標(biāo)識(shí)妆档,如果沒(méi)有key僻爽,vue重新渲染會(huì)選擇就地修改重用相同元素,而使用key則會(huì)根據(jù)key的變化進(jìn)行重新排列贾惦,移除key不存在的元素胸梆。

10. keep-alive

keep-alive用于包裹動(dòng)態(tài)組件,在組件變更時(shí)將其進(jìn)行緩存须板,再次展示時(shí)無(wú)需重新渲染碰镜。

<!-- 失活的組件將會(huì)被緩存!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

11. Vue中組件生命周期調(diào)用順序

組件的調(diào)用順序都是先父后子,渲染完成的順序是先子后父习瑰。
組件的銷(xiāo)毀操作是先父后子绪颖,銷(xiāo)毀完成的順序是先子后父。

加載渲染過(guò)程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子組件更新過(guò)程
父beforeUpdate->子beforeUpdate->子updated->父updated
父組件更新過(guò)程
父 beforeUpdate -> 父 updated
銷(xiāo)毀過(guò)程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

三杰刽、react vs vue

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末菠发,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贺嫂,更是在濱河造成了極大的恐慌滓鸠,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件第喳,死亡現(xiàn)場(chǎng)離奇詭異糜俗,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)曲饱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)悠抹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扩淀,你說(shuō)我怎么就攤上這事楔敌。” “怎么了驻谆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵卵凑,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我胜臊,道長(zhǎng)勺卢,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任象对,我火速辦了婚禮黑忱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己甫煞,他們只是感情好菇曲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著抚吠,像睡著了一般羊娃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上埃跷,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音邮利,去河邊找鬼弥雹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛延届,可吹牛的內(nèi)容都是我干的剪勿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼方庭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼厕吉!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起械念,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤头朱,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后龄减,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體项钮,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年希停,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烁巫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宠能,死狀恐怖亚隙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情违崇,我是刑警寧澤阿弃,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站亦歉,受9級(jí)特大地震影響恤浪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肴楷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一水由、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赛蔫,春花似錦砂客、人聲如沸泥张。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)媚创。三九已至,卻和暖如春彤恶,著一層夾襖步出監(jiān)牢的瞬間钞钙,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工声离, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芒炼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓术徊,卻偏偏與公主長(zhǎng)得像本刽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赠涮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容