VUE面試題
一、v-show 和 v-if的區別,v-show 和 keep-alive 的區別css
答案:v-show是 CSS display 控制顯示和隱藏html
v-if 是組件真正的渲染和銷燬,而不是顯示和隱藏前端
頻繁切換顯示狀態用 v-show,不然用 v-ifvue
keep-alive 是在vue 框架層級進行的JS 對象渲染node
通常簡單的可用 v-show,webpack
複雜一點的通常用 keep-alive,keep-alive 一般用於 tab 的切換git
二、爲什麼 v-for 要用 keygithub
答案:必需要用 key, 並且不能用 index 和 random,web
在 diff 算法中用 tag 和 key來判斷,是不是sameNode面試
能夠減小渲染次數,提升渲染性能
三、描述 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 事件要銷燬
總之就是該銷燬的要在這裏銷燬,不要讓他們留在內存中
具體參考:http://www.javashuo.com/article/p-dfxvszpc-mr.html
多組件生命週期:
- 掛載階段(加載渲染過程):
- 父 beforeCreate --> 父 created --> 父 beforeMount --> 子 beforeCreate --> 子 created --> 子 beforeMount --> 子 mounted --> 父 mounted
- 更新階段:
- 父 beforeUpdate --> 子 beforeUpdate --> 子 updated --> 父 updated
- 銷燬階段:
- 父 beforeDestroy --> 子 beforeDestroy --> 子 destroyed --> 父 destroyed
四、Vue 組件如何通信
答案:
- 父子組件通信:使用屬性和觸發事件,props,$emit,this.$emit 調用父組件的事件,父組件向子組件傳遞一個信息,或者說子組件向父組件觸發一個事件
- 組件之間沒有關係或層級較深:使用自定義事件 ,event是vue實例,vue自己就具備自定義事件的能力。調用自定義事件: event.$emit('xxx', 變量名);綁定自定義事件:event.$on('xxx', 函數名字)。在beforeDestroy 要作的一件事是及時解綁自定義事件,及時銷燬,不然可能形成內存泄漏,寫法:event.$off('xxx', 函數名).
- vuex 通信
五、描述組件渲染和更新的過程
答案:
- 解析模板爲 render 函數(或在開發環境已完成, vue-loader)
- 觸發響應式,監聽 data 屬性 getter,setter
- 執行 render 函數,生成 vnode, patch(elem, vnode)
- 修改 data,觸發 setter (此前在 getter 中 已被 監聽)
- 從新執行 render 函數,生成 newVnode
- patch(vnode, newVnode)
![](http://static.javashuo.com/static/loading.gif)
- 回顧 $nextTick,(如下這是對 $nextTick的回顧: $nextTick: vue 是異步渲染;data改變以後,DOM 不會馬上渲染;$nextTick 會在 DOM 渲染以後被觸發,以獲取最新 DOM 節點。vue 爲什麼是異步渲染,$nextTick何用?異步渲染(以及合併data修改),以提升渲染性能,$nextTick 在DOM 更新完以後,觸發回調。另外,在 vue 中能夠經過 ref 獲取元素:給元素添加ref屬性並設置名稱,而後經過 this.$refs.ref 屬性名稱獲取該DOM 元素)總結:一、異步渲染,$nextTick待 DOM 渲染完再回調;二、頁面渲染時會將 data 的修改作整合,屢次data修改只作一次渲染。
- 彙總 data 的修改,一次性更新視圖
- 減小 DOM 操做次數,提升性能
六、雙向事件綁定 v-model 的實現原理
答案:經過 input 元素的 value = this.name
綁定 input 事件 this.name = $event.target.value
data 更新觸發 re-render
數據雙向綁定的原理可參考:http://www.javashuo.com/article/p-qyeipotc-mq.html 的第3 點
七、對 MVVM 的理解
答案:參考:http://www.javashuo.com/article/p-qyeipotc-mq.html 第一、2點
![](http://static.javashuo.com/static/loading.gif)
八、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 和 watch的使用場景:若是一個數據須要通過複雜計算就用 computed;若是一個數據須要被監聽而且對數據作一些操做就用watch;watch擅長處理的場景:一個數據影響多個數據;computed擅長處理的場景:一個數據受多個數據影響
九、爲什麼組件 data 必須是一個函數?
答案:根本上 .vue 文件編譯出來是一個類,這個組件是一個class,咱們在使用這個組件的時候至關於對class 實現實例化,在實例化的時候執行data,若是 data不是函數的話拿每一個組件的實例結果都同樣了,共享了,若是 data不是函數的話在一個地方改了,另外一個地方也改了。若是data是函數在左邊實例化一個右邊實例化一個都會執行這個函數,這兩個data都在閉包中,兩個不會相互影響
![](http://static.javashuo.com/static/loading.gif)
十、Ajax 請求應該放在哪一個生命週期
答案:應該放在 mounted 生命週期,JS 是單線程的,Ajax 異步獲取數據,放在 mounted 以前沒有用,只會讓邏輯更加混亂
十一、如何將組件全部 props 傳遞給子組件?
答案:$props <user v-bind="$props">
十二、如何本身實現 v-model?
答案:![](http://static.javashuo.com/static/loading.gif)
1三、多個組件有相同邏輯,如何抽離?
答案: 用 mixin, mixin 的一些缺點
mixin 的用法:;定義一個 js文件將export default 中的共有內容寫到裏面,而後在組件中import,放到 mixin數組中
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
mixin 的一些缺點:
- 變量來源不明,不利於閱讀。咱們但願編程紅的變量和方法是可查找的,可是 mixin 引入的內容編輯是不可尋找
- 多mixin 可能形成命名衝突
- 迷信和組件可能出現多對多的關係(一個組件引用多個 mixin, 一個mixin被多個組件引用),複雜度較高。多對可能是最複雜的關係,很容易剪不斷理還亂
在vue3 提出的 Composition API 旨在解決這些問題
1四、什麼時候使用異步組件?
答案:
1五、什麼時候須要使用 keep-alive?
答案:
- 緩存組件,不須要重複渲染
- 如多個靜態 tab 頁的切換
- 優化性能
1六、什麼時候須要使用 beforeDestroy?
答案:
- 解除自定義事件 event.$off
- 清除定時器
- 解綁自定義的 DOM 事件,如 window scroll等
1七、什麼是做用域插槽?
答案:父組件經過 slot 獲取子組件中的的值:子組件中經過自定義屬性綁定數據,父組件經過 template的 v-slot 屬性來接收數據
![](http://static.javashuo.com/static/loading.gif)
1八、vuex 中 action 和 mutation有何區別?
答案:
- action 中處理異步,mutation 不能夠
- mutation 作原子操做
- action 能夠整合多個 mutation
1九、vue-router 經常使用的路由模式
答案:
- hash 默認:有 #,也就是路由的hash,後面是路由
- H5 history(須要服務端支持):沒有 #,須要服務端再次,無特殊需求可選擇 hash模式
20、如何配置 vue-router 異步加載?
答案:異步加載性能會優化不少,配置:component: () => import(......)
![](http://static.javashuo.com/static/loading.gif)
2一、請用 vnode 描述一個 DOM 結構
答案:
![](http://static.javashuo.com/static/loading.gif)
2二、監聽 data 變化的核心 API 是什麼?
答案: Object.defineProperty,以及要想一下如何深度監聽、監聽數組,有何缺點
如何深度監聽:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
如何監聽數組:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
不可像如下這樣作會污染全局的Array 原型:
![](http://static.javashuo.com/static/loading.gif)
缺點:
-
- 深度監聽,須要遞歸到底,一次性計算量大
- 沒法監聽新增/刪除屬性(因此須要 vue.set vue.delete 實現新增/刪除屬性)
- 沒法監聽原生數組,須要特殊處理
2三、vue 如何監聽數組變化
答案:
- Object.defineProperty 不能監聽數組變化
- 從新定義原型,重寫push pop 等方法,實現監聽
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
- Proxy 能夠原生支持監聽數組變化
2四、請描述響應式原理
答案:
![](http://static.javashuo.com/static/loading.gif)
2五、diff 算法的時間複雜度
答案:
O(n)
在O(n^3)基礎上作了一些調整
2六、簡述diff算法過程:
答案:
- patch(elem, vnode) 和 patch(vnode, newVnode)
- patchVnode 和 addVnode 和 removeVnode
- updateChildren(key 的重要性)
2七、Vue 常見性能優化方式
答案:
- 合理使用v-show 和 v-if
- 合理使用computed
- v-for 時要加key,以及避免和 v-if 同時使用
- 自定義事件、DOM 事件及時銷燬
- 合理使用異步組件
- 合理使用keep-alive
- data層級不要太深(由於深度監聽一次性監聽到底)
- 使用 vue-loader 在開發環境作模板編譯(預編譯)
- webpack層面的優化
- 前端通用的性能優化,若是圖片懶加載
- 使用 SSR
2八、vuex
vuex 是一個專門爲 vue.js 應用程序開發的狀態管理模式,它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化.
構建中大型單頁應用是這個狀態管理應該包含如下幾個部分:
- state,驅動應用的數據源
- view,以聲明方式將state映射到視圖
- actions,響應在view上的用戶輸入致使的狀態變化
幾個基本概念(屬性):
- state:單一狀態樹,儲存的單一狀態,是儲存的基本數據.vuex 的狀態儲存是響應式的
- getters:能夠認爲是 store的計算屬性,對 state加工,是派生出來的數據,返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會從新計算
- mutation:更改 vuex 的store中的狀態的惟一方法是提交 mutation(mutation提交修改狀態).每一個mutation 都有一個字符串的事件類型(type)和一個回調函數(handler),這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數,使用 store.commit, (mutation是同步的)
- action: 像一個裝飾器,action提交的是mutation,而不是直接更改狀態,action能夠包含任意異步操做,經過store.dispatch 方法觸發,也可使用 mapAction
- 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是如何掛載注入到組件中的呢?
- 在vue 項目中先安裝 vuex
- 利用vue 的插件機制,使用 vue.use(vuex)時,會調用 vuex 的install方法,安裝 vuex
- 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 面試題
一、前端代碼爲什麼要進行構建和打包
答案:
代碼方面:
- 體積更小(Tree-Shaking、壓縮、合併),加載更快
- 編譯高級語言或語法(TS,ES6+,模塊化,scss)
- 兼容性和錯誤檢查(Polyfilll, postcss, eslint)
研發流程方面:
- 統1、高效的開發環境
- 統一的構建流程和產出標準
- 集成公司構建規範(體測、上線等)
二、module、chunk、bundle分別是什麼意思,有何區別
答案:
- module -- 各個源碼文件,webpack 中一切皆模塊
- chunk -- 多模塊合併成的,如 entry import() splitChunk
- bundle -- 最終的輸出文件
三、loader 和 plugin 的區別
答案:
loader:模塊轉換器,如 less --> css, 如識別 js 結尾的,css 結尾的,圖片格式結尾的,經過 loader 轉換成相應的文件格式
plugin:擴展插件,如 HtmlWebpackPlugin
常見 loader 和 plugin:
https://www.webpackjs.com/loaders/,
本人在項目中經常使用到的loader有
- babel-loader -- This package allows transpiling JavaScript files using Babel and webpack.
- css-loader --
css-loader
解釋(interpret) @import
和 url()
,會 import/require()
後再解析(resolve)它們。引用資源的合適 loader 是 file-loader和 url-loade
- 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()
過
- file-loader -- Instructs webpack to emit the required object as file and to return its public URL
- json-loader -- 注意:因爲
webpack >= v2.0.0
默認支持導入 JSON 文件。若是你使用自定義文件擴展名,你可能仍然須要使用此 loader。See the v1.0.0 -> v2.0.0 Migration Guide for more information
- less-loader -- Compiles Less to CSS.
- postcss-loader -- Loader for webpack to process CSS with PostCSS
- style-loader -- Adds CSS to the DOM by injecting a
<style>
tag
- url-loader -- Loads files as
base64
encoded URL
https://www.webpackjs.com/plugins/
本人在項目中經常使用的 plugin 有:
- HtmlWebpackPlugin(html-webpack-plugin) --
HtmlWebpackPlugin
簡化了HTML文件的建立,以便爲你的webpack包提供服務。這對於在文件名中包含每次會隨着編譯而發生變化哈希的 webpack bundle 尤爲有用。 你可讓插件爲你生成一個HTML文件,使用lodash模板提供你本身的模板,或使用你本身的loader
- ExtractTextWebpackPlugin(extract-text-webpack-plugin)-- Extract text from a bundle, or bundles, into a separate file.
- CopyWebpackPlugin(copy-webpack-plugin)-- Copies individual files or entire directories to the build directory
- UglifyjsWebpackPlugin(uglifyjs-webpack-plugin)-- This plugin uses UglifyJS v3 (
uglify-es
) to minify your JavaScript
- DllPlugin --
DLLPlugin
和 DLLReferencePlugin
用某種方法實現了拆分 bundles,同時還大大提高了構建的速度。
- IgnorePlugin -- 防止在
import
或 require
調用時,生成如下正則表達式匹配的模塊:
-
-
requestRegExp
匹配(test)資源請求路徑的正則表達式。
contextRegExp
(可選)匹配(test)資源上下文(目錄)的正則表達式。
四、babel 和 webpack 的區別
答案:
- Babel --> JS 新語法編譯工具,不關心模塊化
- webpack --> 打包構建工具,是多個 loader plugin的集合
五、webpack 如何實現懶加載
答案:
import()
結合Vue React 異步組件
結合vue-router React-router 異步加載路由
六、爲什麼 Proxy 不能被 Polyfill
答案:
如class 能夠用 function 模擬
如 Promise 能夠用 callback 模擬
但 Proxy 的功能用 Object.defineProperty 沒法模擬(沒有任何一個語法能夠模擬 Proxy)
七、如何產出一個lib
答案:
![](http://static.javashuo.com/static/loading.gif)
八、webpack 常見性能優化
答案:
- 優化 babel-loader
- IgnorePlugin
- noParse
- happyPack
- ParallelUgligyPlugin
- 自動刷新
- 熱更新
- DllPlugin
- 小圖片 base64 編碼
- bundle 加 hash
- 懶加載
- 提取公共代碼
- 使用 CDN 加速
- IgnorePlugin
- 使用 Production
- Scope Hosting
九、babel-runtime 和 babel-polyfill 的區別
答案:
- babel-polyfill 會污染全局
- babel-runtime 不會污染全局
- 產出第三方 lib 要用 babel-runtime
框架綜合應用
一、基於 Vue 設計一個購物車(組件結構,vuex state 數據結構)