<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次在夢里的大廠面試情景

          共 8741字,需瀏覽 18分鐘

           ·

          2021-03-17 14:52

          轉(zhuǎn)自:_楊溜溜
          segmentfault.com/a/1190000023949535

          前言

          昨晚做了一個夢,夢見自己到了一家大廠面試,面試官走近房間,坐了下來:是楊溜溜吧?國際慣例,先來個自我介紹吧。
          于是我巴拉巴拉開始了長達兩分鐘的自我介紹,與此同時,面試官邊聽邊看我的簡歷,邊看邊皺眉,結(jié)束后問:看你之前的項目經(jīng)常用到Vue,對Vue熟悉嗎?
          我嘴角一笑,心里暗喜:幸好有專門看Vue的面試題,看來這次穩(wěn)了。于是謙虛又裝逼的回答:還行吧,您隨便問。
          于是面試官看我口氣那么大,心想:喲嚯,來了一個裝逼的,勞資今天就只問Vue。
          原文地址:
          https://github.com/yacan8/blog/issues/31

          來,先介紹一下Vue的響應式系統(tǒng)

          Vue為MVVM框架,當數(shù)據(jù)模型data變化時,頁面視圖會得到響應更新,其原理對data的getter/setter方法進行攔截(Object.defineProperty或者Proxy),利用發(fā)布訂閱的設計模式,在getter方法中進行訂閱,在setter方法中發(fā)布通知,讓所有訂閱者完成響應。
          在響應式系統(tǒng)中,Vue會為數(shù)據(jù)模型data的每一個屬性新建一個訂閱中心作為發(fā)布者,而監(jiān)聽器watch、計算屬性computed、視圖渲染template/render三個角色同時作為訂閱者,對于監(jiān)聽器watch,會直接訂閱觀察監(jiān)聽的屬性,對于計算屬性computed和視圖渲染template/render,如果內(nèi)部執(zhí)行獲取了data的某個屬性,就會執(zhí)行該屬性的getter方法,然后自動完成對該屬性的訂閱,當屬性被修改時,就會執(zhí)行該屬性的setter方法,從而完成該屬性的發(fā)布通知,通知所有訂閱者進行更新。

          computed與watch的區(qū)別

          計算屬性computed和監(jiān)聽器watch都可以觀察屬性的變化從而做出響應,不同的是:
          計算屬性computed更多是作為緩存功能的觀察者,它可以將一個或者多個data的屬性進行復雜的計算生成一個新的值,提供給渲染函數(shù)使用,當依賴的屬性變化時,computed不會立即重新計算生成新的值,而是先標記為臟數(shù)據(jù),當下次computed被獲取時候,才會進行重新計算并返回。
          而監(jiān)聽器watch并不具備緩存性,監(jiān)聽器watch提供一個監(jiān)聽函數(shù),當監(jiān)聽的屬性發(fā)生變化時,會立即執(zhí)行該函數(shù)。

          介紹一下Vue的生命周期

          beforeCreate:是new Vue()之后觸發(fā)的第一個鉤子,在當前階段data、methods、computed以及watch上的數(shù)據(jù)和方法都不能被訪問。
          created:在實例創(chuàng)建完成后發(fā)生,當前階段已經(jīng)完成了數(shù)據(jù)觀測,也就是可以使用數(shù)據(jù),更改數(shù)據(jù),在這里更改數(shù)據(jù)不會觸發(fā)updated函數(shù)。可以做一些初始數(shù)據(jù)的獲取,在當前階段無法與Dom進行交互,如果非要想,可以通過vm.$nextTick來訪問Dom。
          beforeMount:發(fā)生在掛載之前,在這之前template模板已導入渲染函數(shù)編譯。而當前階段虛擬Dom已經(jīng)創(chuàng)建完成,即將開始渲染。在此時也可以對數(shù)據(jù)進行更改,不會觸發(fā)updated。
          mounted:在掛載完成后發(fā)生,在當前階段,真實的Dom掛載完畢,數(shù)據(jù)完成雙向綁定,可以訪問到Dom節(jié)點,使用$refs屬性對Dom進行操作。
          beforeUpdate:發(fā)生在更新之前,也就是響應式數(shù)據(jù)發(fā)生更新,虛擬dom重新渲染之前被觸發(fā),你可以在當前階段進行更改數(shù)據(jù),不會造成重渲染。
          updated:發(fā)生在更新完成之后,當前階段組件Dom已完成更新。要注意的是避免在此期間更改數(shù)據(jù),因為這可能會導致無限循環(huán)的更新。
          beforeDestroy:發(fā)生在實例銷毀之前,在當前階段實例完全可以被使用,我們可以在這時進行善后收尾工作,比如清除計時器。
          destroyed:發(fā)生在實例銷毀之后,這個時候只剩下了dom空殼。組件已被拆解,數(shù)據(jù)綁定被卸除,監(jiān)聽被移出,子實例也統(tǒng)統(tǒng)被銷毀。

          為什么組件的data必須是一個函數(shù)

          一個組件可能在很多地方使用,也就是會創(chuàng)建很多個實例,如果data是一個對象的話,對象是引用類型,一個實例修改了data會影響到其他實例,所以data必須使用函數(shù),為每一個實例創(chuàng)建一個屬于自己的data,使其同一個組件的不同實例互不影響。

          組件之間是怎么通信的

          • 父子組件通信
          父組件 -> 子組件:prop
          子組件 -> 父組件:$on/$emit
          獲取組件實例:使用$parent/$children,$refs.xxx,獲取到實例后直接獲取屬性數(shù)據(jù)或調(diào)用組件方法
          • 兄弟組件通信
          Event Bus:每一個Vue實例都是一個Event Bus,都支持$on/$emit,可以為兄弟組件的實例之間new一個Vue實例,作為Event Bus進行通信。
          Vuex:將狀態(tài)和方法提取到Vuex,完成共享
          • 跨級組件通信
          使用provide/inject
          Event Bus:同兄弟組件Event Bus通信
          Vuex:將狀態(tài)和方法提取到Vuex,完成共享

          Vue事件綁定原理說一下

          每一個Vue實例都是一個Event Bus,當子組件被創(chuàng)建的時候,父組件將事件傳遞給子組件,子組件初始化的時候是有$on方法將事件注冊到內(nèi)部,在需要的時候使用$emit觸發(fā)函數(shù),而對于原生native事件,使用addEventListener綁定到真實的DOM元素上。

          slot是什么?有什么作用?原理是什么?

          slot又名插槽,是Vue的內(nèi)容分發(fā)機制,組件內(nèi)部的模板引擎使用slot元素作為承載分發(fā)內(nèi)容的出口。插槽slot是子組件的一個模板標簽元素,而這一個標簽元素是否顯示,以及怎么顯示是由父組件決定的。
          slot又分三類,默認插槽,具名插槽和作用域插槽。
          • 默認插槽:又名匿名查抄,當slot沒有指定name屬性值的時候一個默認顯示插槽,一個組件內(nèi)只有有一個匿名插槽。
          • 具名插槽:帶有具體名字的插槽,也就是帶有name屬性的slot,一個組件可以出現(xiàn)多個具名插槽。
          • 作用域插槽:默認插槽、具名插槽的一個變體,可以是匿名插槽,也可以是具名插槽,該插槽的不同點是在子組件渲染作用域插槽時,可以將子組件內(nèi)部的數(shù)據(jù)傳遞給父組件,讓父組件根據(jù)子組件的傳遞過來的數(shù)據(jù)決定如何渲染該插槽。
          實現(xiàn)原理:當子組件vm實例化時,獲取到父組件傳入的slot標簽的內(nèi)容,存放在vm.$slot中,默認插槽為vm.$slot.default,具名插槽為vm.$slot.xxx,xxx 為插槽名,當組件執(zhí)行渲染函數(shù)時候,遇到slot標簽,使用$slot中的內(nèi)容進行替換,此時可以為插槽傳遞數(shù)據(jù),若存在數(shù)據(jù),則可稱該插槽為作用域插槽。

          Vue模板渲染的原理是什么?

          vue中的模板template無法被瀏覽器解析并渲染,因為這不屬于瀏覽器的標準,不是正確的HTML語法,所有需要將template轉(zhuǎn)化成一個JavaScript函數(shù),這樣瀏覽器就可以執(zhí)行這一個函數(shù)并渲染出對應的HTML元素,就可以讓視圖跑起來了,這一個轉(zhuǎn)化的過程,就成為模板編譯。
          模板編譯又分三個階段,解析parse,優(yōu)化optimize,生成generate,最終生成可執(zhí)行函數(shù)render。
          • parse階段:使用大量的正則表達式對template字符串進行解析,將標簽、指令、屬性等轉(zhuǎn)化為抽象語法樹AST。
          • optimize階段:遍歷AST,找到其中的一些靜態(tài)節(jié)點并進行標記,方便在頁面重渲染的時候進行diff比較時,直接跳過這一些靜態(tài)節(jié)點,優(yōu)化runtime的性能。
          • generate階段:將最終的AST轉(zhuǎn)化為render函數(shù)字符串。

          template預編譯是什么?

          對于 Vue 組件來說,模板編譯只會在組件實例化的時候編譯一次,生成渲染函數(shù)之后在也不會進行編譯。因此,編譯對組件的 runtime 是一種性能損耗。微信搜索公眾號 逆鋒起筆,關注后回復 編程資源,領取各種經(jīng)典學習資料。
          而模板編譯的目的僅僅是將template轉(zhuǎn)化為render function,這個過程,正好可以在項目構(gòu)建的過程中完成,這樣可以讓實際組件在 runtime 時直接跳過模板渲染,進而提升性能,這個在項目構(gòu)建的編譯template的過程,就是預編譯。

          那template和jsx的有什么分別?

          對于 runtime 來說,只需要保證組件存在 render 函數(shù)即可,而我們有了預編譯之后,我們只需要保證構(gòu)建過程中生成 render 函數(shù)就可以。
          在 webpack 中,我們使用vue-loader編譯.vue文件,內(nèi)部依賴的vue-template-compiler模塊,在 webpack 構(gòu)建過程中,將template預編譯成 render 函數(shù)。
          與 react 類似,在添加了jsx的語法糖解析器babel-plugin-transform-vue-jsx之后,就可以直接手寫render函數(shù)。
          所以,template和jsx的都是render的一種表現(xiàn)形式,不同的是:
          JSX相對于template而言,具有更高的靈活性,在復雜的組件中,更具有優(yōu)勢,而 template 雖然顯得有些呆滯。但是 template 在代碼結(jié)構(gòu)上更符合視圖與邏輯分離的習慣,更簡單、更直觀、更好維護。

          說一下什么是Virtual DOM

          Virtual DOM 是 DOM 節(jié)點在 JavaScript 中的一種抽象數(shù)據(jù)結(jié)構(gòu),之所以需要虛擬DOM,是因為瀏覽器中操作DOM的代價比較昂貴,頻繁操作DOM會產(chǎn)生性能問題。虛擬DOM的作用是在每一次響應式數(shù)據(jù)發(fā)生變化引起頁面重渲染時,Vue對比更新前后的虛擬DOM,匹配找出盡可能少的需要更新的真實DOM,從而達到提升性能的目的。

          介紹一下Vue中的Diff算法

          在新老虛擬DOM對比時
          • 首先,對比節(jié)點本身,判斷是否為同一節(jié)點,如果不為相同節(jié)點,則刪除該節(jié)點重新創(chuàng)建節(jié)點進行替換
          • 如果為相同節(jié)點,進行patchVnode,判斷如何對該節(jié)點的子節(jié)點進行處理,先判斷一方有子節(jié)點一方?jīng)]有子節(jié)點的情況(如果新的children沒有子節(jié)點,將舊的子節(jié)點移除)
          • 比較如果都有子節(jié)點,則進行updateChildren,判斷如何對這些新老節(jié)點的子節(jié)點進行操作(diff核心)。
          • 匹配時,找到相同的子節(jié)點,遞歸比較子節(jié)點
          在diff中,只對同層的子節(jié)點進行比較,放棄跨級的節(jié)點比較,使得時間復雜從O(n^3)降低值O(n),也就是說,只有當新舊children都為多個子節(jié)點時才需要用核心的Diff算法進行同層級比較。

          key屬性的作用是什么

          在對節(jié)點進行diff的過程中,判斷是否為相同節(jié)點的一個很重要的條件是key是否相等,如果是相同節(jié)點,則會盡可能的復用原有的DOM節(jié)點。所以key屬性是提供給框架在diff的時候使用的,而非開發(fā)者。

          說說Vue2.0和Vue3.0有什么區(qū)別

          1. 重構(gòu)響應式系統(tǒng),使用Proxy替換Object.defineProperty,使用Proxy優(yōu)勢:

            • 可直接監(jiān)聽數(shù)組類型的數(shù)據(jù)變化
            • 監(jiān)聽的目標為對象本身,不需要像Object.defineProperty一樣遍歷每個屬性,有一定的性能提升
            • 可攔截apply、ownKeys、has等13種方法,而Object.defineProperty不行
            • 直接實現(xiàn)對象屬性的新增/刪除
          2. 新增Composition API,更好的邏輯復用和代碼組織

          3. 重構(gòu) Virtual DOM

            • 模板編譯時的優(yōu)化,將一些靜態(tài)節(jié)點編譯成常量
            • slot優(yōu)化,將slot編譯為lazy函數(shù),將slot的渲染的決定權交給子組件
            • 模板中內(nèi)聯(lián)事件的提取并重用(原本每次渲染都重新生成內(nèi)聯(lián)函數(shù))
          4. 代碼結(jié)構(gòu)調(diào)整,更便于Tree shaking,使得體積更小

          5. 使用Typescript替換Flow

          為什么要新增Composition API,它能解決什么問題

          Vue2.0中,隨著功能的增加,組件變得越來越復雜,越來越難維護,而難以維護的根本原因是Vue的API設計迫使開發(fā)者使用watch,computed,methods選項組織代碼,而不是實際的業(yè)務邏輯。
          另外Vue2.0缺少一種較為簡潔的低成本的機制來完成邏輯復用,雖然可以minxis完成邏輯復用,但是當mixin變多的時候,會使得難以找到對應的data、computed或者method來源于哪個mixin,使得類型推斷難以進行。
          所以Composition API的出現(xiàn),主要是也是為了解決Option API帶來的問題,第一個是代碼組織問題,Compostion API可以讓開發(fā)者根據(jù)業(yè)務邏輯組織自己的代碼,讓代碼具備更好的可讀性和可擴展性,也就是說當下一個開發(fā)者接觸這一段不是他自己寫的代碼時,他可以更好的利用代碼的組織反推出實際的業(yè)務邏輯,或者根據(jù)業(yè)務邏輯更好的理解代碼。
          第二個是實現(xiàn)代碼的邏輯提取與復用,當然mixin也可以實現(xiàn)邏輯提取與復用,但是像前面所說的,多個mixin作用在同一個組件時,很難看出property是來源于哪個mixin,來源不清楚,另外,多個mixin的property存在變量命名沖突的風險。而Composition API剛好解決了這兩個問題。

          都說Composition API與React Hook很像,說說區(qū)別

          從React Hook的實現(xiàn)角度看,React Hook是根據(jù)useState調(diào)用的順序來確定下一次重渲染時的state是來源于哪個useState,所以出現(xiàn)了以下限制
          • 不能在循環(huán)、條件、嵌套函數(shù)中調(diào)用Hook
          • 必須確??偸窃谀愕腞eact函數(shù)的頂層調(diào)用Hook
          • useEffect、useMemo等函數(shù)必須手動確定依賴關系
          而Composition API是基于Vue的響應式系統(tǒng)實現(xiàn)的,與React Hook的相比
          • 聲明在setup函數(shù)內(nèi),一次組件實例化只調(diào)用一次setup,而React Hook每次重渲染都需要調(diào)用Hook,使得React的GC比Vue更有壓力,性能也相對于Vue來說也較慢
          • Compositon API的調(diào)用不需要顧慮調(diào)用順序,也可以在循環(huán)、條件、嵌套函數(shù)中使用
          • 響應式系統(tǒng)自動實現(xiàn)了依賴收集,進而組件的部分的性能優(yōu)化由Vue內(nèi)部自己完成,而React Hook需要手動傳入依賴,而且必須必須保證依賴的順序,讓useEffect、useMemo等函數(shù)正確的捕獲依賴變量,否則會由于依賴不正確使得組件性能下降。
          雖然Compositon API看起來比React Hook好用,但是其設計思想也是借鑒React Hook的。

          SSR有了解嗎?原理是什么?

          在客戶端請求服務器的時候,服務器到數(shù)據(jù)庫中獲取到相關的數(shù)據(jù),并且在服務器內(nèi)部將Vue組件渲染成HTML,并且將數(shù)據(jù)、HTML一并返回給客戶端,這個在服務器將數(shù)據(jù)和組件轉(zhuǎn)化為HTML的過程,叫做服務端渲染SSR。
          而當客戶端拿到服務器渲染的HTML和數(shù)據(jù)之后,由于數(shù)據(jù)已經(jīng)有了,客戶端不需要再一次請求數(shù)據(jù),而只需要將數(shù)據(jù)同步到組件或者Vuex內(nèi)部即可。除了數(shù)據(jù)意外,HTML也結(jié)構(gòu)已經(jīng)有了,客戶端在渲染組件的時候,也只需要將HTML的DOM節(jié)點映射到Virtual DOM即可,不需要重新創(chuàng)建DOM節(jié)點,這個將數(shù)據(jù)和HTML同步的過程,又叫做客戶端激活。
          使用SSR的好處:
          • 有利于SEO:其實就是有利于爬蟲來爬你的頁面,因為部分頁面爬蟲是不支持執(zhí)行JavaScript的,這種不支持執(zhí)行JavaScript的爬蟲抓取到的非SSR的頁面會是一個空的HTML頁面,而有了SSR以后,這些爬蟲就可以獲取到完整的HTML結(jié)構(gòu)的數(shù)據(jù),進而收錄到搜索引擎中。
          • 白屏時間更短:相對于客戶端渲染,服務端渲染在瀏覽器請求URL之后已經(jīng)得到了一個帶有數(shù)據(jù)的HTML文本,瀏覽器只需要解析HTML,直接構(gòu)建DOM樹就可以。而客戶端渲染,需要先得到一個空的HTML頁面,這個時候頁面已經(jīng)進入白屏,之后還需要經(jīng)過加載并執(zhí)行 JavaScript、請求后端服務器獲取數(shù)據(jù)、JavaScript 渲染頁面幾個過程才可以看到最后的頁面。特別是在復雜應用中,由于需要加載 JavaScript 腳本,越是復雜的應用,需要加載的 JavaScript 腳本就越多、越大,這會導致應用的首屏加載時間非常長,進而降低了體驗感。

          更多詳情查看 徹底理解服務端渲染-SSR原理 https://github.com/yacan8/blog/issues/30

          結(jié)束

          面試官點了點頭,嗯呢,這小伙還可以,懂得還挺多,可以弄進來寫業(yè)務。
          我也暗自竊喜,幸虧沒問到我不會的,然后我坐那傻笑,笑著笑著,突然聽到我的鬧鈴響了,然后,我夢醒了。

          然后,新的搬磚的一天又開始了。

          字節(jié)跳動的 8 輪視頻面試流程

          記自己 2018 年三月份的面試經(jīng)歷

          15 個常見的 Node.js 面試問題及答案

          程序員面試 10 大潛規(guī)則,千萬不要踩坑!

          聊聊我的一次真實 Python 面試經(jīng)歷


              
          點個『在看』支持下 
          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人无码网站 | 欧美老妇人与禽交 | 色五月天网站 | 国产乱妇无码毛片A片在线看下载 | 91靠逼视频|