寫在前面
之前有提到,在經(jīng)歷了前端轉(zhuǎn)型之后,一場技術(shù)變革的到來,小程序,h5移動端,對性能優(yōu)化的要求越來越高,受面向?qū)ο笏枷刖幊谭绞降挠绊懀岸爽F(xiàn)在主流的技術(shù)框架就是Vue,React,Angular.他們的數(shù)據(jù)驅(qū)動模式,MVVM模式,很受歡迎,這種spa單頁面應(yīng)用,組件思維對一個龐大的web應(yīng)用很有幫助提升加載速度,減少Dom操作,隨之而來的也就是不斷地學(xué)習(xí),對技術(shù)員的技術(shù)要求也開始偏向于vue,小程序,公眾號,由于智能手機的普及,app端比網(wǎng)頁更受歡迎,所以就要不斷地學(xué)習(xí)新的知識,否則會被淘汰。
在面試的時候肯定免不了被問到其他知識點例如es6,javascript,css3
我也總結(jié)出來了,詳情請移步
好了,不說廢話了,總結(jié)一下使用vue開發(fā)項目過程中遇到的坑以及面試經(jīng)驗。
這里關(guān)于v-model原理的僅限于vue3.0以下版本,聽說vue3.0不在采用
Object.defineProperty
,具體的還有待學(xué)習(xí),完了了解了再來更新。vue3.0的響應(yīng)式原理已經(jīng)更新,詳情請移步vue2.0和3.0的響應(yīng)式原理以及區(qū)別
step一,談?wù)勀銓VVM 的理解?
- MVVM 由 Model,View,ViewModel 三部分構(gòu)成,Model 層代表數(shù)據(jù)模型,也可以在Model中定義數(shù)據(jù)修改和操作的業(yè)務(wù)邏輯;View 代表UI 組件,它負(fù)責(zé)將數(shù)據(jù)模型轉(zhuǎn)化成UI 展現(xiàn)出來,ViewModel 是一個同步View 和 Model的對象。
在MVVM架構(gòu)下,View 和 Model 之間并沒有直接的聯(lián)系,而是通過ViewModel進(jìn)行交互,Model 和 ViewModel 之間的交互是雙向的, 因此View 數(shù)據(jù)的變化會同步到Model中,而Model 數(shù)據(jù)的變化也會立即反應(yīng)到View 上。
ViewModel 通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來,而View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發(fā)者只需關(guān)注業(yè)務(wù)邏輯,不需要手動操作DOM, 不需要關(guān)注數(shù)據(jù)狀態(tài)的同步問題,復(fù)雜的數(shù)據(jù)狀態(tài)維護(hù)完全由 MVVM 來統(tǒng)一管理。
step二,vue路由傳參的方式
- router.js 后邊跟:id配置參數(shù)
- query 方法傳參
- name 方法傳參
- vue自帶標(biāo)簽<router-link :to>標(biāo)簽傳參
- 詳情請看Vue $router 路由傳參的3種方法詳解
step三,vue組件之間的傳參
- 父傳子 props
- 子傳父 this.$emit
- 非父子組件 eventHub 中轉(zhuǎn)站 this.$on
- vuex state 存的變量,mutations改變的狀態(tài) actions 觸發(fā)的行為(方法)
組件傳參具體的傳參請參考vue2.0父子組件以及非父子組件通信傳參詳解
vuex stroe 具體的請參考vuex原理,用法踩坑小計
step四,vue-router有哪幾種導(dǎo)航鉤子?
答案
- 第一種是全局導(dǎo)航鉤子(全局守衛(wèi)):router.beforeEach(to,from,next),作用:跳轉(zhuǎn)前進(jìn)行判斷攔截。
- 第 二種:全局解析守衛(wèi)
router.beforeResolve
,在導(dǎo)航被確認(rèn)前,所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調(diào)用。(2.5.0新增)。 - 第三種:單獨路由獨享的守衛(wèi)
beforeEnter
,在路由配置時定義,與全局守衛(wèi)的方法是一樣的。 - 第四種:組件內(nèi)的守衛(wèi)。直接在路由組件內(nèi)定義守衛(wèi),
以下為官網(wǎng)文檔的介紹:
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應(yīng)路由被 confirm 前調(diào)用
// 不!能!獲取組件實例 `this`
// 因為當(dāng)守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建
},
beforeRouteUpdate (to, from, next) {
// 在當(dāng)前路由改變,但是該組件被復(fù)用時調(diào)用
// 舉例來說,對于一個帶有動態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時候,
// 由于會渲染同樣的 Foo 組件,因此組件實例會被復(fù)用。而這個鉤子就會在這個情況下被調(diào)用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用
// 可以訪問組件實例 `this`
}
step五,請寫出幾種常用的vue指令
v-once、v-for、v-if、v-show、v-on,v-model
step六,請詳細(xì)解釋一下vue(2.0)的生命周期?
答案:
生命周期 | 階段 | 描述 |
---|---|---|
beforeCreated | 創(chuàng)建前 | vue實例的掛載元素$el和數(shù)據(jù)對象data都為undefined,還未初始化。 |
created | 創(chuàng)建后 | vue實例的數(shù)據(jù)對象data有了,$el還沒有。 |
beforeMount | 模板載入前 | vue實例的$el和data都初始化了,但還是掛載之前為虛擬的dom節(jié)點,data.message還未替換 |
mounted | 模板載入后 | vue實例掛載完成,data.message成功渲染。 |
beforeUpdate | 組件更新前 | 組件更新之前調(diào)用 |
updated | 組件更新后 | 組件更新之后調(diào)用 |
beforeDestroy | 組件銷毀前 | 調(diào)用$destroy方法后,立即執(zhí)行beforeDestroy |
pdestroyed | 組件銷毀后 | 組件銷毀后調(diào)用,此時只剩下dom空殼 |
step七,slot是什么?并說一下詳細(xì)的用法?
答案:
這里邊都是vue2.0的slot插槽的知識。3.0更新了
vue官網(wǎng)解釋:slot 插槽,-------(Vue 實現(xiàn)了一套內(nèi)容分發(fā)的 API,這套 API 基于當(dāng)前的 Web Components 規(guī)范草案,將
<slot>
元素作為承載分發(fā)內(nèi)容的出口。
)是不是看完稀里糊涂的,反正我是稀里糊涂的,再來說說我自己的理解:
slot就是為了實現(xiàn)真正的靈活的單頁組件,在組件外部靈活控制組件內(nèi)部的內(nèi)容一種形式或者是入口,就是將組件內(nèi)所需要的內(nèi)容以插槽(slot)的形式插入到公共組件中,以達(dá)到靈活控制。
當(dāng)組件渲染的時候,這個 <slot> 元素將會被替換為“Your Profile”。插槽內(nèi)可以包含任何模板代碼,包括 HTML:詳情請看vue 帶動畫效果的NavBar這里邊有詳細(xì)介紹到<slot>
的使用方法。
這里邊是3.0的slot插槽的內(nèi)容
- 1, vue 3.0將插槽當(dāng)做了一個標(biāo)簽
<slot></slot>
2, 定義一個插槽<div class="main"> <slot name="header"></slot> </div>
3, 向插槽內(nèi)分發(fā)內(nèi)容<template v-slot:header><p>這里是插入插槽中的內(nèi)容</p></template>
也可以寫為<template #header><p>
4,v-slot
只能添加在<template>
上。除獨占默認(rèn)插槽
除外。
具體請看官方文檔
slot.png
step八,談?wù)勀銓ue響應(yīng)式原理的理解?
詳情請移步vue2.0和3.0的響應(yīng)式原理以及區(qū)別
step九,直接對對象屬性進(jìn)行添加和刪除會不會直接響應(yīng)到視圖中?也就是說數(shù)組的更新方法?并說明原因?
答案:
直接對對象屬性進(jìn)行添加和刪除是不會響應(yīng)到視圖中的,需要用到this.$set()方法
舉個例子
var vm = new Vue({
data:{
myjson:{
name:"張三"
}
}
})
vm.myjson.age= "12"; //這樣直接對對象屬性進(jìn)行增加是不會直接響應(yīng)到視圖中的。
需要這么寫:
this.$set(this.myjson,'age',12);//才會生效
原因
受現(xiàn)代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到對象屬性的添加或刪除。由于 Vue 會在初始化實例時對屬性執(zhí)行 getter/setter 轉(zhuǎn)化過程,所以屬性必須在 data 對象上存在才能讓 Vue 轉(zhuǎn)換它,這樣才能讓它是響應(yīng)的。
step十,如何創(chuàng)建一個公共的全局組件,并在每個頁面中調(diào)用以及如何創(chuàng)建并調(diào)用公共的方法?
答案:
將創(chuàng)建好的組件或者js方法導(dǎo)出并掛載到vue實例上。
詳情請參考關(guān)于vue全局引用公共的js和公共的組件的折騰
step十一,請說明v-if
和v-show
的異同?
同:兩者都是達(dá)到顯示隱藏的功能
異:
-
v-if
指令是直接銷毀和重建DOM達(dá)到讓元素顯示和隱藏的效果 -
v-show
指令通過修改元素的display屬性讓其顯示或者隱藏
step十二,<keep-alive></keep-alive>
的作用是什么?
答案:
<keep-alive></keep-alive>
包裹動態(tài)組件時,會緩存不活動的組件實例,主要用于保留組件狀態(tài)或避免重新渲染。
用自己的理解說
比如有一個列表和一個詳情,那么用戶就會經(jīng)常執(zhí)行打開詳情=>返回列表=>打開詳情…這樣的話列表和詳情都是一個頻率很高的頁面,那么就可以對列表組件使用<keep-alive></keep-alive>進(jìn)行緩存,這樣用戶每次返回列表的時候,都能從緩存中快速渲染,而不是重新渲染,這樣就會減輕服務(wù)器壓力,提高性能。
step十三,<router-link>
屬性以及方法?
答案:
-
:to
相當(dāng)于a標(biāo)簽中的"herf"屬性,后面跟跳轉(zhuǎn)鏈接所用 ,會渲染成a標(biāo)簽--<a href="url">
<router-link :to="/home">Home</router-link>
<!-- 渲染結(jié)果 -->
<a href="/home">Home</a>
-
replace
屬性,加上該屬性頁面切換不會留下歷史紀(jì)錄。
<router-link :to="/home" replace></router-link>
-
tag
屬性,具有tag屬性的router-link會被渲染成相應(yīng)的標(biāo)簽
<router-link :to="/home" tag="li">Home</router-link>
<!-- 渲染結(jié)果 -->
<li>Home</li>
此時頁面的li同樣會起到a鏈接跳轉(zhuǎn)的結(jié)果,vue會自動為其綁定點擊事件,并跳轉(zhuǎn)頁面
-
active-class
屬性:設(shè)置鏈接激活時的class屬性:默認(rèn)值為router-link-active,所以如果沒有設(shè)置,就會被渲染為這個class,我們可以在router.js里邊配置這個屬性
const router = new VueRouter({
mode: 'hash',
linkActiveClass: 'u-link--Active', // 這是鏈接激活時的class
})
<router-link :to="/home" active-class="u-link--Active">Home</router-link>
-
exact
屬性:嚴(yán)格模式
// 這個鏈接只會在地址為 / 的時候被激活
<router-link to="/" exact>Home</router-link>
<router-link to="/user">USER</router-link>
<router-link to="/user/userinfo">USER-info</router-link>
// 如果不設(shè)置exact,則當(dāng)路由到了/user/userinfo 頁面時,USER也是被設(shè)置了router-link-active樣式的!
- 方法:
router-link默認(rèn)是觸發(fā)router.push(location),如果設(shè)置的replace 則觸發(fā)router.replace(location),這有啥區(qū)別呢?
router.push() :導(dǎo)航跑到不同的URL,這個方法會向history棧添加一個新的記錄,所以,當(dāng)用戶點擊瀏覽器后退按鈕時,則回到之前的url.
router.replace(): 跟router.push作用是一樣的,但是,它不會向history添加新記錄,而是跟它的方法名一樣替換掉當(dāng)前的history記錄.
router.go(n): 這個方法的參數(shù)是一個整數(shù),意思是在history記錄中向前或者后退多少步,類似window.history.go(n)
step十四,v-once
的作用和用法?
只渲染元素和組件一次,隨后的渲染,使用了此指令的元素/組件及其所有的子節(jié)點,都會當(dāng)作靜態(tài)內(nèi)容并跳過,這可以用于優(yōu)化更新性能。
舉個例子:一看便知
<template>
<div>
<div>{{count}}</div>
<button v-on:click="addCount">改變count的值</button>
</div>
</template>
<script>
export default {
name: "VueOnce",
data() {
return {
count: "我是不可改變的"
}
},
methods: {
addCount: function () {
this.count = "我就要改變你";
此時這個操作dom里邊的count是不會變化的
}
}
}
</script>
<style scoped>
</style>
step十五,如何解決在加載頁面時出現(xiàn)的閃爍問題。
v-cloak
詳情請移步v-cloak詳解
step十六,vue如何兼容ie的問題。
答案:
回答關(guān)鍵字
- babel-polyfill插件
詳情請移步vue-cli 解決ie兼容性問題
step十七,vue-cli如何解決跨域?
答案:常見的后臺加請求頭以及jsonp就不詳細(xì)解釋了,若要看詳細(xì)教程請移步前端面試題總結(jié)。
這里主要介紹的是 npm模塊之http-proxy-middleware的解決跨域的辦法。詳情移步vue-cli如何解決跨域
step十八,vue如何在父組件中調(diào)用子組件的方法。
答案:
回答關(guān)鍵字
- ref
詳情請移步vue如何在父組件中調(diào)用子組件的方法
step十九,談?wù)勀銓?code>minxins混入的理解以及使用方法
詳情請移步深入淺出之vue-cli混入(mixins)的理解和使用
step 二十,談?wù)勀銓atch(偵聽器)和 computed (計算屬性)理解以及二者的區(qū)別。
詳情請移步vue watch - 偵聽器和computed - 計算屬性 的理解和使用
step 二十一, 你知道為什么 vue 或者 react ,angular
這些mvvm框架 比傳統(tǒng)的操作dom渲染速度要快么?
- 答案就是vue用的是虛擬dom.
step 二十二,v-if
和v-for
誰的優(yōu)先級高
答案: v-for的優(yōu)先級高,所以也就是說如果他倆在一起使用時,v-if
會運行很多遍,解決辦法就是在循環(huán)的模版外邊套一層框子,在這個框子上使用v-if
就好了。
step 二十三,v-on
可以綁定多個方法嗎?
答案:可以,直接在后邊跟上就可以了
<div v-on="{click:myclick,mouseleave:myMouseleave}"></div>
- 不了解虛擬dom的同學(xué)請移步vue之虛擬dom的認(rèn)識與理解