天天看點

前端工程師常見面試題(前端進階)——Vue 架構

有使用過 Vue 嗎?說說你對 Vue 的了解

參考回答:

Vue 是一個建構資料驅動的漸進性架構,它的目标是通過 API 實作響應資料綁定和視圖 更新。

說說 Vue 的優缺點

參考回答:

優點:

1、資料驅動視圖,對真實 dom 進行抽象出virtual dom (本質就是一個 js 對象) , 并配合 diff 算法 、響應式和觀察者 、異步隊列等手段以最小代價更新dom, 渲染 頁面

2 、元件化, 元件用單檔案的形式進行代碼的組織編寫, 使得我們可以在一個文 件裡編寫 html\css (scoped 屬性配置 css 隔離) \js 并且配合 Vue-loader 之後, 支 持更強大的預處理器等功能

3 、強大且豐富的 API 提供一系列的 api 能滿足業務開發中各類需求

4 、 由于采用虛拟 dom, 讓 Vue ssr 先天就足

5 、生命周期鈎子函數, 選項式的代碼組織方式, 寫熟了還是蠻順暢的, 但仍然 有優化空間 ( Vue3 composition-api)

6 、生态好, 社群活躍 缺點:

(1) 、 由于底層基于 Object.defineProperty 實作響應式, 而這個 api 本身不支援 IE8 及以下浏覽器

(2) 、csr 的先天不足, 首屏性能問題 (白屏)

(3)、 由于百度等搜尋引擎爬蟲無法爬取 js 中的内容, 故 spa 先天就對 seo 優化心 有餘力不足 (谷歌的 puppeteer 就挺牛逼的, 實作預渲染底層也是用到了這個工具)

Vue 和 React 有什麼不同? 使用場景分别是什麼?

參考回答:

1、Vue 是完整一套由官方維護的架構, 核心庫主要有由尤雨溪大神獨自維護, 而 React 是不要臉的書維護 (很多庫由社群維護) ,曾經一段時間很多人質疑 Vue 的後續維護性, 似乎這并不是問題。

2 、Vue 上手簡單, 進階式架構, 白話說你可以學一點, 就可以在你項目中去用一點, 你不一定需要一次性學習整個 Vue 才能去使用它, 而 React, 恐怕如果你這樣會面對項 目束手無策。

3、文法上 Vue 并不限制你必須 es6+完全 js 形式編寫頁面,可以視圖和 js 邏輯盡可能分 離, 減少很多人看不慣 React-jsx 的惡心嵌套, 畢竟都是作為前端開發者, 還是更習慣 于 html 幹淨。

4、很多人說 React 适合大型項目,适合什麼什麼,Vue 輕量級,适合移動端中小型項目, 其實我想說,說這話的人是心裡根本沒點逼數,Vue 完全可以應對複雜的大型應用,甚 至于說如果你 React 學的不是很好,寫出來的東西或根本不如 Vue 寫的,畢竟 Vue 跟着 官方文檔撸就行, 自有人幫你規範, 而 React 比較懶散自由, 可以自由發揮

5、Vue 在國内人氣明顯勝過 React,這很大程度上得益于它的很多文法包括程式設計思維更 符合國人思想。

什麼是虛拟 DOM?

參考回答:

虛拟 dom 是相對于浏覽器所渲染出來的真實 dom 的, 在 react, vue 等技術出現之前, 我們要改變頁面展示的内容隻能通過周遊查詢 dom 樹的方式找到需要修改的 dom 然 後修改樣式行為或者結構, 來達到更新 ui 的目的。

這種方式相當消耗計算資源, 因為每次查詢 dom 幾乎都需要周遊整顆 dom 樹, 如果 建立一個與 dom 樹對應的虛拟 dom 對象 ( js 對象) ,以對象嵌套的方式來表示 dom 樹,那麼每次 dom 的更改就變成了 js 對象的屬性的更改,這樣一來就能查找 js 對象 的屬性變化要比查詢 dom 樹的性能開銷小。

請描述下 vue 的生命周期是什麼?

參考回答:

生命周期就是 vue 從開始建立到銷毀的過程,分為四大步 (建立,挂載, 更新,銷毀) ,每一步又分為兩小步,如 beforeCreate,created。beforeCreate 前, 也就是 new Vue 的時候會初始化事件和生命周期;

beforeCreate 和 created 之間會挂載 Data,綁定事件;

接下來會根據 el 挂載頁面元素,如 果沒有設定 el 則生命周期結束, 直到手動挂載;

el 挂載結束後, 根據 templete/outerHTML(el)渲染頁面;

在 beforeMount 前虛拟 DOM 已經建立完成;

之後在 mounted 前,将 vm.$el 替換掉頁面元素 el;

mounted 将虛拟 dom 挂載到真實頁面 (此時頁面已經全部渲染完成) ;

之後發生資料變化時 觸發 beforeUpdate 和 updated 進行一些操作;

最後主動調用銷毀函數或者 元件自動銷毀時 beforeDestroy,手動撤銷監聽事件,計時器等;

destroyed 時僅存在 Dom 節點, 其他所有東西已自動銷毀 。這就是我所了解的vue 的一個完整的生命周期。

前端工程師常見面試題(前端進階)——Vue 架構

vue 如何監聽鍵盤事件?

參考回答:

1. @keyup. 方法

<template>

<input ref="myInput" type="text" value="hello world" autofocus

@keyup.enter="handleKey">

</template>

<script>

export default {

methods: {

handleKey(e) {

console.log(e)

}

}

}

</script>           

2. addEventListener

<script>

export default {

mounted() {

document.addEventListener('keyup', this.handleKey)

},

beforeDestroy() {

document.removeEventListener('keyup', this.handleKey)

},

methods: {

handleKey(e) {

console.log(e)

}

}

}

</script>

<script>

export default {

mounted() {

document.addEventListener('keyup', this.handleKey)

},

beforeDestroy() {

document.removeEventListener('keyup', this.handleKey)

},

methods: {

handleKey(e) {

console.log(e)

}

}

}

</script>           

watch 怎麼深度監聽對象變化

參考回答:

deep 設定為true 就可以監聽到對象的變化

let vm=new Vue({

el:"#first",

data:{msg:{name:'北京'}},

watch:{

msg:{

handler (newMsg,oldMsg){

console.log(newMsg);

},

immediate:true,

deep:true

}

}

})           

删除數組用 delete 和 Vue.delete 有什麼差別?

參考回答:

delete: 隻是被删除數組成員變為 empty / undefined, 其他元素鍵值不變 Vue.delete: 直接删了數組成員, 并改變了數組的鍵值 (對象是響應式的, 確定

删除能觸發更新視圖,這個方法主要用于避開 Vue 不能檢測到屬性被删除的限 制)

watch 和計算屬性有什麼差別?

參考回答:

通俗來講,既能用 computed 實作又可以用 watch 監聽來實作的功能,推薦用 computed, 重點在于 computed 的緩存功能

computed 計算屬性是用來聲明式的描述一個值依賴了其它的值,當所依賴的值或者變量 改變時, 計算屬性也會跟着改變;

watch 監聽的是已經在 data 中定義的變量,當該變量變化時,會觸發 watch 中的方法。

Vue 雙向綁定原理

參考回答:

Vue 資料雙向綁定是通過資料劫持結合釋出者-訂閱者模式的方式來實作的 。利用了 Object.defineProperty() 這個方法重新定義了對象擷取屬性值(get)和設定屬性值(set)。

v-model 是什麼?有什麼用呢?

參考回答:

一則文法糖,相當于 v-bind:value="xxx" 和 @input,意思是綁定了一個 value 屬性的值, 子元件可對 value 屬性監聽, 通過$emit('input', xxx)的方式給父元件通訊 。 自己實作 v-model 方式的元件也是這樣的思路。

axios 是什麼? 怎樣使用它? 怎麼解決跨域的問題?

參考回答:

axios 的是一種異步請求,用法和 ajax 類似,安裝 npm install axios --save 即可使用,請 求中包括 get,post,put, patch ,delete 等五種請求方式, 解決跨域可以在請求頭中添加 Access-Control-Allow-Origin, 也可以在 index.js 檔案中更改 proxyTable 配置等解決跨域 問題。

在 vue 項目中如何引入第三方庫 (比如 jQuery) ?有哪些方法可以做到?

參考回答:

1 、絕對路徑直接引入

在 index.html 中用 script 引入

<script src="./static/jquery-1.12.4.js"></script>           

然後在 webpack 中配置 external

externals: { 'jquery': 'jQuery' }           

在元件中使用時 import

import $ from 'jquery'           

2 、在 webpack 中配置 alias

resolve: { extensions: ['.js', '.vue', '.json'], alias: { '@': resolve('src'), 'jquery': resolve('static/jquery-1.12.4.js') } }           

然後在元件中 import

3 、在 webpack 中配置 plugins

plugins: [ new webpack.ProvidePlugin({ $: 'jquery' }) ]           

全局使用, 但在使用eslint 情況下會報錯, 需要在使用了 $ 的代碼前添加 /* eslint-disable*/ 來去掉 ESLint 的檢查。

說說 Vue React angularjs jquery 的差別

參考回答:

JQuery 與另外幾者最大的差別是, JQuery 是事件驅動, 其他兩者是資料驅動。

JQuery 業務邏輯和 UI 更改該混在一起, UI 裡面還參雜這互動邏輯, 讓本來混亂的邏 輯更加混亂。

Angular, Vue 是雙向綁定, 而 React 不是

其他還有設計理念上的差別等

Vue3.0 裡為什麼要用 Proxy API 替代 defineProperty API?

參考回答:

響應式優化。

a. defineProperty API 的局限性最大原因是它隻能針對單例屬性做監聽。

Vue2.x 中的響應式實作正是基于 defineProperty 中的 descriptor,對 data 中的屬性做了遍 曆 + 遞歸, 為每個屬性設定了 getter 、setter。

這也就是為什麼 Vue 隻能對 data 中預定義過的屬性做出響應的原因, 在 Vue 中使用 下标的方式直接修改屬性的值或者添加一個預先不存在的對象屬性是無法做到setter 監 聽的, 這是 defineProperty 的局限性。

b. ProxyAPI 的監聽是針對一個對象的,那麼對這個對象的所有操作會進入監聽操作, 這 就完全可以代理所有屬性, 将會帶來很大的性能提升和更優的代碼。

Proxy 可以了解成, 在目标對象之前架設一層“攔截”, 外界對該對象的通路, 都必須 先通過這層攔截, 是以提供了一種機制, 可以對外界的通路進行過濾和改寫。

c. 響應式是惰性的

在 Vue.js 2.x 中,對于一個深層屬性嵌套的對象,要劫持它内部深層次的變化,就需要 遞歸周遊這個對象, 執行 Object.defineProperty 把每一層對象資料都變成響應式的, 這 無疑會有很大的性能消耗。

在 Vue.js 3.0 中,使用 Proxy API 并不能監聽到對象内部深層次的屬性變化,是以它的 處理方式是在 getter 中去遞歸響應式,這樣的好處是真正通路到的内部屬性才會變成響 應式, 簡單的可以說是按需實作響應式, 減少性能消耗。

基礎用法:

前端工程師常見面試題(前端進階)——Vue 架構

Vue3.0 編譯做了哪些優化?

參考回答:

a. 生成 Block tree

Vue.js 2.x 的資料更新并觸發重新渲染的粒度是元件級的,單個元件内部 需要周遊該組 件的整個 vnode 樹。在 2.0 裡,渲染效率的快慢與元件大小成正相關:元件越大,渲染 效率越慢 。并且, 對于一些靜态節點, 又無資料更新, 這些周遊都是性能浪費。

Vue.js 3.0 做到了通過編譯階段對靜态模闆的分析, 編譯生成了 Block tree 。 Block tree 是一個将模版基于動态節點指令切割的嵌套區塊,每個 區塊内部的節點結構是固定的, 每個區塊隻需要追蹤自身包含的動态節點 。是以, 在 3.0 裡, 渲染效率不再與模闆大小 成正相關, 而是與模闆中動态節點的數量成正相關。

b. slot 編譯優化

Vue.js 2.x 中,如果有一個元件傳入了slot,那麼每次父元件更新的時候,會強制使子組 件 update, 造成性能的浪費。

Vue.js 3.0 優化了 slot 的生成, 使得非動态 slot 中屬性的更新隻會觸發子元件的更新。

動态 slot 指的是在 slot 上面使用 v-if, v-for, 動态 slot 名字等會導緻 slot 産生運作時動 态變化但是又無法被子元件 track 的操作。

c. diff 算法優化

Vue3.0 新特性 —— Composition API 與 React.js 中 Hooks 的異同點

參考回答:

a. React.js 中的 Hooks 基本使用

React Hooks 允許你 "勾入" 諸如元件狀态和副作用處理等 React 功能中 。Hooks 隻能 用在函數元件中,并允許我們在不需要建立類的情況下将狀态、副作用處理和更多東西 帶入元件中。

React 核心團隊奉上的采納政策是不反對類元件,是以你可以更新 React 版本、在新組 件中開始嘗試 Hooks, 并保持既有元件不做任何更改。

案例:

前端工程師常見面試題(前端進階)——Vue 架構

useState 和 useEffect 是 React Hooks 中的一些例子, 使得函數元件中也能增加狀态和 運作副作用。

我們也可以自定義一個 Hooks, 它打開了代碼複用性和擴充性的新大門。

b. Vue Composition API 基本使用

Vue Composition API 圍繞一個新的元件選項 setup 而建立。setup() 為 Vue 元件提供了 狀态 、計算值 、watcher 和生命周期鈎子。

并沒有讓原來的 API ( Options-based API) 消失 。允許開發者 結合使用新舊兩種 API (向下相容) 。

前端工程師常見面試題(前端進階)——Vue 架構

c. 原理

React hook 底層是基于連結清單實作,調用的條件是每次元件被 render 的時候都會順序執行 所有的 hooks。

Vuehook 隻會被注冊調用一次, Vue 能避開這些麻煩的問題, 原因在于它對資料的響 應是基于 proxy 的,對資料直接代理觀察 。 (這種場景下, 隻要任何一個更改 data 的地 方, 相關的 function 或者 template 都會被重新計算, 是以避開了 React 可能遇到的性能 上的問題) 。

React 中, 資料更改的時候, 會導緻重新 render, 重新 render 又會重新把 hooks 重新注 冊一次, 是以 React 複雜程度會高一些。

Vue3.0 是如何變得更快的? (底層, 源碼)

參考回答:

a. diff 方法優化

Vue2.x 中的虛拟 dom 是進行全量的對比。

Vue3.0 中新增了靜态标記 ( PatchFlag) : 在與上次虛拟結點進行對比的時候, 值對比 帶有 patch flag 的節點, 并且可以通過 flag 的資訊得知目前節點要對比的具體内容化。

b. hoistStatic 靜态提升

Vue2.x : 無論元素是否參與更新, 每次都會重新建立。

Vue3.0 : 對不參與更新的元素,隻會被建立一次,之後會在每次渲染時候被不停的複用。

c. cacheHandlers 事件偵聽器緩存

預設情況下 onClick 會被視為動态綁定, 是以每次都會去追蹤它的變化但是因為是同一 個函數, 是以沒有追蹤變化, 直接緩存起來複用即可。

vue 要做權限管理該怎麼做? 如果控制到按鈕級别的權限怎麼做?

參考回答:

按鈕級别的權限:

vue 在 created 和 mounted 這兩個生命周期中請求資料有什麼差別呢?

參考回答:

看實際情況, 一般在 created (或 beforeRouter) 裡面就可以, 如果涉及到需要頁面加載 完成之後的話就用mounted。

在 created 的時候,視圖中的 html 并沒有渲染出來,是以此時如果直接去操作 html 的 dom 節點, 一定找不到相關的元素

而在mounted 中, 由于此時 html 已經渲染出來了, 是以可以直接操作 dom 節點, (此 時 document.getelementById 即可生效了) 。

說說你對 proxy 的了解

參考回答:

vue 的資料劫持有兩個缺點:

1 、無法監聽通過索引修改數組的值的變化

2 、無法監聽 object 也就是對象的值的變化

是以vue2.x 中才會有$set 屬性的存在

proxy 是 es6 中推出的新 api, 可以彌補以上兩個缺點, 是以 vue3.x 版本用 proxy 替換 object.defineproperty。

繼續閱讀