前端面試題匯總


VUE面試題

1、v-show 和 v-if的區別,v-show 和 keep-alive 的區別

答案:v-show是 CSS display 控制顯示和隱藏

v-if 是組件真正的渲染和銷毀,而不是顯示和隱藏

頻繁切換顯示狀態用 v-show,否則用 v-if

keep-alive 是在vue 框架層級進行的JS 對象渲染

一般簡單的可用 v-show,

復雜一點的一般用 keep-alive,keep-alive 通常用於 tab 的切換

2、為何 v-for 要用 key

答案:必須要用 key, 而且不能用 index 和 random,

key是vue中vnode的唯一標記,通過這個key,我們的diff操作可以更准確,更快速

在 diff 算法中用 tag 和 key來判斷,是否是sameNode

可以減少渲染次數,提高渲染性能

3、描述 Vue 組件生命周期(有父子組件的情況)

答案:單組件生命周期,生命周期可分為

  • 掛載階段(
    • beforeCreate:此階段為實例初始化之后,此時數據觀察和事件機制還沒有形成,不能獲取到dom節點;
    • created:此階段的vue實例已經創建,仍不能獲取DOM 節點.把vue 的一個實例給初始化了,只是存在於 js 內存的一個變量而已,這個時候並沒有開始渲染;
    • beforeMount:在這一階段,我們雖然還不能獲取到具體 DOM 元素,但 vue 掛載的根節點已經創建,下面 vue 對DOM 的操作將圍繞這個根元素繼續進行,beforeMount 這個階段是過渡性的,一般一個項目只能用到一兩次;
    • mounted:組件真正繪制完成了,頁面已經渲染完了,數據和DOM 都已被渲染出來,一般我們的異步請求都寫在這里)
  • 更新階段(
    • beforeUpdate: 這一階段,vue遵循數據驅動DOM 的原則,beforeUpdate 函數在數據更新后沒有立即更新數據,但是DOM 數據會改變,這是雙向數據綁定的作用;
    • updated:這一階段,DOM 會和更改過的內容同步)
  • 銷毀階段(
    • beforeDestroy:在上一階段vue已經成功通過數據驅動DOM 的修改,當我們不再需要 vue 操縱 DOM 時,就要銷毀 vue,也就是清除vue 實例與 DOM 的關聯,調用destroy方法可以銷毀當前組件。在銷毀前,會觸發 beforeDestroy 鈎子函數;
    • destroyed:在銷毀后,會觸發destroyed 鈎子函數)

beforeDestroy要做的事:

  • 自定義事件解除綁定:(eventBus 等)
  • 銷毀定時任務:(setTimeout,setInterval等)
  • 綁定的window 或 document 事件要銷毀

總之就是該銷毀的要在這里銷毀,不要讓他們留在內存中

具體參考:https://www.cnblogs.com/queenya/p/13416654.html

多組件生命周期:

  • 掛載階段(加載渲染過程):
  • 父 beforeCreate --> 父 created --> 父 beforeMount --> 子 beforeCreate --> 子 created --> 子 beforeMount --> 子 mounted --> 父 mounted
  • 更新階段:
  • 父 beforeUpdate --> 子 beforeUpdate --> 子 updated --> 父 updated
  • 銷毀階段:
  • 父 beforeDestroy --> 子 beforeDestroy --> 子 destroyed --> 父 destroyed

 

4、Vue 組件如何通訊

答案:

  • 父子組件通訊:使用屬性和觸發事件,props,$emit,this.$emit 調用父組件的事件,父組件向子組件傳遞一個信息,或者說子組件向父組件觸發一個事件
  • 組件之間沒有關系或層級較深:使用自定義事件 ,event是vue實例,vue本身就具有自定義事件的能力。調用自定義事件: event.$emit('xxx', 變量名);綁定自定義事件:event.$on('xxx', 函數名字)。在beforeDestroy 要做的一件事是及時解綁自定義事件,及時銷毀,否則可能造成內存泄漏,寫法:event.$off('xxx', 函數名).
  • vuex 通訊

5、描述組件渲染和更新的過程

答案:

  • 初次渲染過程:
  1. 解析模板為 render 函數(或在開發環境已完成, vue-loader)
  2. 觸發響應式,監聽 data 屬性 getter,setter
  3. 執行 render 函數,生成 vnode, patch(elem, vnode)
  • 更新過程:
  1. 修改 data,觸發 setter (此前在 getter 中 已被 監聽)
  2. 重新執行 render 函數,生成 newVnode
  3. patch(vnode, newVnode)

  • 異步渲染:
  1. 回顧 $nextTick,(以下這是對 $nextTick的回顧: $nextTick: vue 是異步渲染;data改變之后,DOM 不會立刻渲染;$nextTick 會在 DOM 渲染之后被觸發,以獲取最新 DOM 節點。vue 為何是異步渲染,$nextTick何用?異步渲染(以及合並data修改),以提高渲染性能,$nextTick 在DOM 更新完之后,觸發回調。另外,在 vue 中可以通過 ref 獲取元素:給元素添加ref屬性並設置名稱,然后通過 this.$refs.ref 屬性名稱獲取該DOM 元素)總結:1、異步渲染,$nextTick待 DOM 渲染完再回調;2、頁面渲染時會將 data 的修改做整合,多次data修改只做一次渲染。
  2. 匯總 data 的修改,一次性更新視圖
  3. 減少 DOM 操作次數,提高性能

6、雙向事件綁定 v-model 的實現原理

答案:通過 input 元素的 value = this.name

綁定 input 事件 this.name = $event.target.value

data 更新觸發 re-render

數據雙向綁定的原理可參考:https://www.cnblogs.com/queenya/p/13426695.html 的第3 點

7、對 MVVM 的理解

答案:參考:https://www.cnblogs.com/queenya/p/13426695.html 第1、2點

8、computed 有何特點,computed 和 watch,methods 的區別

答案:

  • computed: 有緩存,data 不變不會重新計算;提高性能。
  • computed 為什么需要緩存?簡單說就是可以提高性能。假設我們有一個性能開銷比較大的計算屬性A,它需要遍歷一個巨大的數組做大量的計算,然后我們可能有其他的屬性依賴於A,如果沒有緩存,將不可避免的多次執行A 的getter,如果不希望有緩存請用方法代替
  • computed 和 methods的區別: computed 計算屬性是基於它的響應式依賴進行緩存的,只在相關響應式依賴發生改變時它們才會重新求值,這意味着只要原屬性還沒發生改變,多次訪問相關屬性,計算屬性會立即返回之前的計算結果,而不必再次執行函數;而 methods 每當觸發重新渲染時,調用方法總會再次執行函數
  • computed 和 watch的區別:computed 默認只要 getter,不過需要時也可以提供 setter;watch 偵聽器,當需要在數據變化時執行異步或開銷較大的操作時,watch是最有用的,使用 watch選項允許執行異步操作(訪問一個API),限制我們執行該操作的頻率,並在得到最終結果前,設置中間狀態,這些都是計算屬性無法做到的

  • computed 是屬性
  1. 當需要根據已有數據產生一些派生數據的時候,可使用計算屬性
  2. 注意:計算屬性不支持異步操作,因為計算屬性一般要綁定到模板中
  3. 更重要的一點是:計算屬性會緩存調用的結果,提高性能
  4. 計算屬性必須有返回值,沒有返回值就沒有意義
  • watch 是一個功能:
  1. watch不需要返回值,根據某個數據變化執行xx邏輯
  2. watch可以執行異步操作

  • computed 和 watch的使用場景:如果一個數據需要經過復雜計算就用 computed;如果一個數據需要被監聽並且對數據做一些操作就用watch;watch擅長處理的場景:一個數據影響多個數據;computed擅長處理的場景:一個數據受多個數據影響

9、為何組件 data 必須是一個函數?

答案:防止組件重用的時候導致數據相互影響。根本上 .vue 文件編譯出來是一個類,這個組件是一個class,我們在使用這個組件的時候相當於對class 實現實例化,在實例化的時候執行data,如果 data不是函數的話拿每個組件的實例結果都一樣了,共享了,如果 data不是函數的話在一個地方改了,另一個地方也改了。如果data是函數在左邊實例化一個右邊實例化一個都會執行這個函數,這兩個data都在閉包中,兩個不會相互影響

10、Ajax 請求應該放在哪個生命周期

答案:應該放在 mounted 生命周期,JS 是單線程的,Ajax 異步獲取數據,放在 mounted 之前沒有用,只會讓邏輯更加混亂

11、如何將組件所有 props 傳遞給子組件?

答案:$props  <user v-bind="$props">

12、如何自己實現 v-model?

答案:

13、多個組件有相同邏輯,如何抽離?

答案: 用 mixin, mixin 的一些缺點

mixin 的用法:;定義一個 js文件將export default 中的共有內容寫到里面,然后在組件中import,放到 mixin數組中

 

mixin 的一些缺點:

  1. 變量來源不明,不利於閱讀。我們希望編程紅的變量和方法是可查找的,但是 mixin 引入的內容編輯是不可尋找
  2. 多mixin 可能造成命名沖突
  3. 迷信和組件可能出現多對多的關系(一個組件引用多個 mixin, 一個mixin被多個組件引用),復雜度較高。多對多是最復雜的關系,很容易剪不斷理還亂

在vue3 提出的 Composition API 旨在解決這些問題

14、何時使用異步組件?

答案:

  • 加載大組件
  • 路由異步加載

15、何時需要使用 keep-alive?

答案:

  • 緩存組件,不需要重復渲染
  • 如多個靜態 tab 頁的切換
  • 優化性能

16、何時需要使用 beforeDestroy?

答案:

  • 解除自定義事件 event.$off
  • 清除定時器
  • 解綁自定義的 DOM 事件,如 window scroll等

 17、什么是作用域插槽?

答案:父組件通過 slot 獲取子組件中的的值:子組件中通過自定義屬性綁定數據,父組件通過 template的 v-slot 屬性來接收數據

18、vuex 中 action 和 mutation有何區別?

答案:

  • action 中處理異步,mutation 不可以
  • mutation 做原子操作
  • action 可以整合多個 mutation

19、vue-router 常用的路由模式

答案:

  • hash 默認:有 #,也就是路由的hash,后面是路由
  • H5 history(需要服務端支持):沒有 #,需要服務端再次,無特殊需求可選擇 hash模式

20、如何配置 vue-router 異步加載?

答案:異步加載性能會優化很多,配置:component: () => import(......)

21、請用 vnode 描述一個 DOM 結構

答案:

22、監聽 data 變化的核心 API 是什么?

答案: Object.defineProperty,以及要想一下如何深度監聽、監聽數組,有何缺點

如何深度監聽:

 

如何監聽數組:

不可像以下這樣做會污染全局的Array 原型:

缺點:

    • 深度監聽,需要遞歸到底,一次性計算量大
    • 無法監聽新增/刪除屬性(所以需要 vue.set vue.delete 實現新增/刪除屬性)
    • 無法監聽原生數組,需要特殊處理

23、vue 如何監聽數組變化

答案:

  • Object.defineProperty 不能監聽數組變化
  • 重新定義原型,重寫push pop 等方法,實現監聽
  • Proxy 可以原生支持監聽數組變化

24、請描述響應式原理

答案:

25、diff 算法的時間復雜度

答案:

O(n)

在O(n^3)基礎上做了一些調整

26、簡述diff算法過程:

答案:

  • patch(elem, vnode) 和 patch(vnode, newVnode)
  • patchVnode 和 addVnode 和 removeVnode
  • updateChildren(key 的重要性)

27、Vue 常見性能優化方式

答案:

  • 合理使用v-show 和 v-if
  • 合理使用computed
  • v-for 時要加key,以及避免和 v-if 同時使用
  • 自定義事件、DOM 事件及時銷毀
  • 合理使用異步組件
  • 合理使用keep-alive
  • data層級不要太深(因為深度監聽一次性監聽到底)
  • 使用 vue-loader 在開發環境做模板編譯(預編譯)
  • webpack層面的優化
  • 前端通用的性能優化,如果圖片懶加載
  • 使用 SSR

28、vuex

vuex 是一個專門為 vue.js 應用程序開發的狀態管理模式,它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化.

構建中大型單頁應用是這個狀態管理應該包含以下幾個部分:

  • state,驅動應用的數據源
  • view,以聲明方式將state映射到視圖
  • actions,響應在view上的用戶輸入導致的狀態變化

幾個基本概念(屬性):

  1. state:單一狀態樹,儲存的單一狀態,是儲存的基本數據.vuex 的狀態儲存是響應式的
  2. getters:可以認為是 store的計算屬性,對 state加工,是派生出來的數據,返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會重新計算
  3. mutation:更改 vuex 的store中的狀態的唯一方法是提交 mutation(mutation提交修改狀態).每個mutation 都有一個字符串的事件類型(type)和一個回調函數(handler),這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個參數,使用 store.commit, (mutation是同步的)
  4. action: 像一個裝飾器,action提交的是mutation,而不是直接更改狀態,action可以包含任意異步操作,通過store.dispatch 方法觸發,也可以使用 mapAction
  5. module: 是 store 分割的模塊,每個模塊擁有直接的 state,getter,mutation,action, 甚至是嵌套子模塊 -- 從上至下進行同樣方式的分割模塊內部的 action,局部狀態通過 context.state暴露出來,根節點則為 context.rootState

用於Vue 組件(API):

  • dispatch
  • commit
  • mapState
  • mapGetters
  • mapMutations
  • mapActions

vuex設計思想,借鑒了 Flux,Redux,將數據存放到全局的store,再將 store掛載到每個 vue實例組件中,利用 vue.js 的細粒對數據響應機制來進行高效的狀態更新

vuex的store是如何掛載注入到組件中的呢?

  1. 在vue 項目中先安裝 vuex
  2. 利用vue 的插件機制,使用 vue.use(vuex)時,會調用 vuex 的install方法,安裝 vuex
  3. applyMixin 方法使用 vue 混入機制,vue的生命周期 beforeCreate 鈎子函數混入 vuexInit 方法

vuex是利用 vue 的 mixin 混入機制,在beforeCreate 鈎子函數混入 vuexInit 方法,vuexInit 方法實現了 store 注入 vue 組件實例,並注冊了 vuex store 的引用屬性 $store

vuex 的state 和 getter 是如何映射到各個組件實例中響應式更新狀態的?

vuex 的state 狀態是響應式,是借助 vue的data是響應式,將 state存入vue實例組件的data中;vuex 的getters則是借助 vue的計算屬性 computed 實現數據實時監聽

Webpack 面試題

1、前端代碼為何要進行構建和打包

答案:

代碼方面:

  • 體積更小(Tree-Shaking、壓縮、合並),加載更快
  • 編譯高級語言或語法(TS,ES6+,模塊化,scss)
  • 兼容性和錯誤檢查(Polyfilll, postcss, eslint)

  研發流程方面:

  • 統一、高效的開發環境
  • 統一的構建流程和產出標准
  • 集成公司構建規范(體測、上線等)

2、module、chunk、bundle分別是什么意思,有何區別

答案:

  • module -- 各個源碼文件,webpack 中一切皆模塊
  • chunk -- 多模塊合並成的,如 entry import() splitChunk
  • bundle -- 最終的輸出文件

3、loader 和 plugin 的區別

答案:

loader:模塊轉換器,如 less --> css, 如識別 js 結尾的,css 結尾的,圖片格式結尾的,通過 loader 轉換成相應的文件格式

plugin:擴展插件,如 HtmlWebpackPlugin

常見 loader 和 plugin:

https://www.webpackjs.com/loaders/

本人在項目中常用到的loader有

  1. babel-loader -- This package allows transpiling JavaScript files using Babel and webpack.
  2. css-loader -- css-loader 解釋(interpret) @import 和 url() ,會 import/require() 后再解析(resolve)它們。引用資源的合適 loader 是 file-loader和 url-loade
  3. expose-loader -- The expose loader adds modules to the global object. This is useful for debugging, or supporting libraries that depend on libraries in globals.,模塊必須在你的 bundle 中被 require() 過
  4. file-loader -- Instructs webpack to emit the required object as file and to return its public URL
  5. json-loader -- 注意:由於 webpack >= v2.0.0 默認支持導入 JSON 文件。如果你使用自定義文件擴展名,你可能仍然需要使用此 loader。See the v1.0.0 -> v2.0.0 Migration Guide for more information
  6. less-loader -- Compiles Less to CSS.
  7. postcss-loader -- Loader for webpack to process CSS with PostCSS
  8. style-loader --  Adds CSS to the DOM by injecting a <style> tag
  9. url-loader -- Loads files as base64 encoded URL

https://www.webpackjs.com/plugins/

本人在項目中常用的 plugin 有:

  1. HtmlWebpackPlugin(html-webpack-plugin) -- HtmlWebpackPlugin簡化了HTML文件的創建,以便為你的webpack包提供服務。這對於在文件名中包含每次會隨着編譯而發生變化哈希的 webpack bundle 尤其有用。 你可以讓插件為你生成一個HTML文件,使用lodash模板提供你自己的模板,或使用你自己的loader
  2. ExtractTextWebpackPlugin(extract-text-webpack-plugin)-- Extract text from a bundle, or bundles, into a separate file.
  3. CopyWebpackPlugin(copy-webpack-plugin)-- Copies individual files or entire directories to the build directory
  4. UglifyjsWebpackPlugin(uglifyjs-webpack-plugin)-- This plugin uses UglifyJS v3 (uglify-es) to minify your JavaScript
  5. DllPlugin -- DLLPlugin 和 DLLReferencePlugin 用某種方法實現了拆分 bundles,同時還大大提升了構建的速度。
  6. IgnorePlugin -- 防止在 import 或 require 調用時,生成以下正則表達式匹配的模塊:
      • requestRegExp 匹配(test)資源請求路徑的正則表達式。
      • contextRegExp (可選)匹配(test)資源上下文(目錄)的正則表達式。

4、babel 和 webpack 的區別

答案:

  • Babel --> JS 新語法編譯工具,不關心模塊化
  • webpack --> 打包構建工具,是多個 loader plugin的集合

5、webpack 如何實現懶加載

答案:

import()

結合Vue React 異步組件

結合vue-router React-router 異步加載路由

6、為何 Proxy 不能被 Polyfill

答案:

如class 可以用 function 模擬

如 Promise 可以用 callback 模擬

但 Proxy 的功能用 Object.defineProperty 無法模擬(沒有任何一個語法可以模擬 Proxy)

7、如何產出一個lib

答案:

 

 

8、webpack 常見性能優化

答案:

  • webpack 優化構建速度(可用於生產)
  1. 優化 babel-loader
  2. IgnorePlugin
  3. noParse
  4. happyPack
  5. ParallelUgligyPlugin
  • webpack 優化構建速度(不可用於生產)
  1. 自動刷新
  2. 熱更新
  3. DllPlugin
  • webpack 優化產出代碼
  1. 小圖片 base64 編碼
  2. bundle 加 hash
  3. 懶加載
  4. 提取公共代碼
  5. 使用 CDN 加速
  6. IgnorePlugin
  7. 使用 Production
  8. Scope Hosting

9、babel-runtime 和 babel-polyfill 的區別

答案:

  • babel-polyfill 會污染全局
  • babel-runtime 不會污染全局
  • 產出第三方 lib 要用 babel-runtime

 

框架綜合應用

1、基於 Vue 設計一個購物車(組件結構,vuex state 數據結構)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM