1.v-show 與 v-if 區(qū)別
v-show 是css隱藏陈瘦,v-if是直接銷毀和創(chuàng)建,所以頻繁切換的適合用v-show
2.計(jì)算屬性和 watch 的區(qū)別
計(jì)算屬性是自動(dòng)監(jiān)聽依賴值的變化,從而動(dòng)態(tài)返回內(nèi)容剪个,監(jiān)聽是一個(gè)過程滋迈,在監(jiān)聽的值變化時(shí),可以觸發(fā)一個(gè)回調(diào)益愈,并做一些事情梢灭。
所以區(qū)別來源于用法,只是需要?jiǎng)討B(tài)值蒸其,那就用計(jì)算屬性敏释;需要知道值的改變后執(zhí)行業(yè)務(wù)邏輯,才用 watch摸袁,用反或混用雖然可行钥顽,但都是不正確的用法。
說出一下區(qū)別會(huì)加分
computed 是一個(gè)對(duì)象時(shí)靠汁,它有哪些選項(xiàng)耳鸯?
computed 和 methods 有什么區(qū)別湿蛔?
computed 是否能依賴其它組件的數(shù)據(jù)?
watch 是一個(gè)對(duì)象時(shí)县爬,它有哪些選項(xiàng)阳啥?
有g(shù)et和set兩個(gè)選項(xiàng)
methods是一個(gè)方法,它可以接受參數(shù)财喳,而computed不能察迟,computed是可以緩存的,methods不會(huì)耳高。
computed可以依賴其他computed扎瓶,甚至是其他組件的data
watch 配置
handler
deep 是否深度
immeditate 是否立即執(zhí)行
總結(jié)
當(dāng)有一些數(shù)據(jù)需要隨著另外一些數(shù)據(jù)變化時(shí),建議使用computed泌枪。
當(dāng)有一個(gè)通用的響應(yīng)數(shù)據(jù)變化的時(shí)候概荷,要執(zhí)行一些業(yè)務(wù)邏輯或異步操作的時(shí)候建議使用watcher
3.事件修飾符
綁定一個(gè)原生的click事件, 加native碌燕,
其他事件修飾符
stop(阻止事件冒泡) prevent(阻止默認(rèn)事件)? self(只有自己觸發(fā)误证,子組件不會(huì)觸發(fā))
組合鍵
click.ctrl.exact 只有ctrl被按下的時(shí)候才觸發(fā)
4.雙向綁定的原理
通過數(shù)據(jù)劫持和發(fā)布訂閱模式方式實(shí)現(xiàn)的,核心的 API 是通過Object.defineProperty()來劫持各個(gè)屬性的setter / getter修壕,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者愈捅,觸發(fā)相應(yīng)的監(jiān)聽回調(diào),這也是為什么 Vue.js 2.x 不支持 IE8 的原因慈鸠。要實(shí)現(xiàn)雙向綁定蓝谨,首先進(jìn)行數(shù)據(jù)劫持,所以需要設(shè)置一個(gè)監(jiān)聽器Observer青团,用來監(jiān)聽所有屬性譬巫。如果屬性發(fā)生變化,就需要告訴訂閱者Watcher看是否需要更新督笆。因?yàn)橛嗛喺吆芏嗦簦孕枰粋€(gè)消息訂閱器Dep來專門收集這些訂閱者,然后在監(jiān)聽器和訂閱者之間進(jìn)行統(tǒng)一管理胖腾,最后需要一個(gè)指令解析器Compile,對(duì)每個(gè)節(jié)點(diǎn)元素進(jìn)行掃描和解析瘪松,將相關(guān)指令(v-model咸作,v-on)對(duì)應(yīng)初始化一個(gè)訂閱者Watcheer?? ,并替換模板數(shù)據(jù)或綁定相應(yīng)函數(shù)
官網(wǎng)解釋:https://cn.vuejs.org/v2/guide/reactivity.html
5.怎么理解單項(xiàng)數(shù)據(jù)流
這是關(guān)于組件通訊中父組件的prop傳遞給子組件宵睦,在子組件中不能更改prop记罚,只能父組件更改prop,否則會(huì)報(bào)錯(cuò)壳嚎。子組件想修改時(shí)桐智,只能通過 $emit 派發(fā)一個(gè)自定義事件末早,父組件接收到后,由父組件修改说庭。
一般來說然磷,對(duì)于子組件想要更改父組件狀態(tài)的場景,可以有兩種方案:
在子組件的 data 中拷貝一份 prop刊驴,data 是可以修改的姿搜,但 prop 不能:
exportdefault{props: {value:String},? data () {return{currentValue:this.value? ? }? }}復(fù)制代碼
如果是對(duì) prop 值的轉(zhuǎn)換,可以使用計(jì)算屬性:
exportdefault{props: ['size'],computed: {normalizedSize:function(){returnthis.size.trim().toLowerCase();? ? }? }}
6.簡述vue的狀態(tài)管理并說明你在項(xiàng)目中哪些地方使用了
component通過mapactions或者dispatch將方法類型和負(fù)載傳給actions捆憎,actions接收到后進(jìn)行業(yè)務(wù)處理通過commit將處理后的類型和負(fù)載傳給mutations舅柜,mutations不做業(yè)務(wù)處理,只根據(jù)接收的類型和負(fù)載將state中的數(shù)據(jù)進(jìn)行突變躲惰,component通過mapgetters拿到更新后的倉庫數(shù)據(jù)致份。
在組件中用mapactions接管methods方法,用mapgetters接管computed計(jì)算屬性础拨,這樣主要是為了action更簡潔氮块,便于后期迭代更新。以下通過官網(wǎng)例子進(jìn)行加深理解:
7.簡述下生命周期鉤子
vue實(shí)例從創(chuàng)建到銷毀的過程太伊,就是生命周期雇锡。從開始創(chuàng)建,初始化數(shù)據(jù)僚焦,編譯模板锰提,掛載DOM,渲染芳悲,更新再渲染立肘,最后到銷毀等一系列過程就是生命周期。
beforeCreate:數(shù)據(jù)觀測和初始化事件還沒開始
Created:完成數(shù)據(jù)觀測名扛,屬性和方法的運(yùn)算谅年,初始化事件,$el屬性還沒顯示出來
beforeMount:掛載前調(diào)用肮韧,相關(guān)的render第一次調(diào)用融蹂。實(shí)例已經(jīng)完成編譯模板,data里的數(shù)據(jù)和模板已經(jīng)生成HTML弄企,但沒有講HTML掛載到頁面上
Mounted:el被新創(chuàng)建的Vm.$el替換超燃,并掛載到實(shí)例上面調(diào)用。實(shí)例已經(jīng)完成以下配置:用上面編譯好的HTML內(nèi)容替換el屬性指向DOM元素拘领。完成模板中HTML渲染到HTML頁面中意乓。此過程進(jìn)行ajax交互。
beforeUpdate:發(fā)生在虛擬dom和打補(bǔ)丁之前约素,可以在該鉤子中進(jìn)一步修改狀態(tài)届良,不會(huì)觸發(fā)附加的沖渲染過程笆凌。
Updated:由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補(bǔ)丁之后調(diào)用。調(diào)用時(shí)士葫,組件DOM已經(jīng)更新乞而,所以可以執(zhí)行依賴于DOM的操作。然而在大多數(shù)情況下为障,應(yīng)該避免在此期間更改狀態(tài)晦闰,因?yàn)檫@可能會(huì)導(dǎo)致更新無限循環(huán)。該鉤子在服務(wù)器端渲染期間不被調(diào)用鳍怨。
beforeDestroy(銷毀前) 在實(shí)例銷毀之前調(diào)用呻右。實(shí)例仍然完全可用。
destroyed(銷毀后) 在實(shí)例銷毀之后調(diào)用鞋喇。調(diào)用后声滥,所有的事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀侦香。該鉤子在服務(wù)器端渲染期間不被調(diào)用落塑。
8.組件中如何通信
九叔說要講半小時(shí)左右:。罐韩。憾赁。。
父到子:
傳<子組件 :自定義屬性=“父數(shù)據(jù)”>
收:子組件選項(xiàng)props:【‘自定義屬性’】
子到父:
父組件向子組件傳遞事件方法散吵,子組件通過$emit觸發(fā)事件龙考,回調(diào)給父組件
非父子,兄弟組件通訊:
可以通過實(shí)例一個(gè)vue實(shí)例Bus作為媒介矾睦,要相互通信的兄弟組件之中晦款,都引入Bus,然后通過分別調(diào)用Bus事件觸發(fā)和監(jiān)聽來實(shí)現(xiàn)通信和參數(shù)傳遞枚冗。
9.路由守衛(wèi)是什么缓溅,有幾種方式
全局守衛(wèi),路由獨(dú)享守衛(wèi)赁温,組件內(nèi)部守衛(wèi)坛怪;
全局守衛(wèi):
router.beforeRouteEnter(to,from,next){前置守衛(wèi),進(jìn)入}
router.beforeRouterLeave(to,from,next){后置守衛(wèi)股囊,離開}
to? 目標(biāo)路由? from?? 當(dāng)前路由??
next函數(shù):next() == next(true) 運(yùn)行跳轉(zhuǎn)
?? next(false) 不讓跳轉(zhuǎn)
?? next('字符路徑')/next({對(duì)象路徑}) 重定向
路由獨(dú)享守衛(wèi):沒有后置守衛(wèi)
{
? ? ? path: '/foo',
? ? ? component: Foo,
? ? ? beforeEnter: (to, from, next) => {
? ? ? ? // ...
? ? ? }
? ? }
組件內(nèi)部守衛(wèi):
const Foo = {
? template: `...`,
? beforeRouteEnter (to, from, next) {? 前置
? ? // 在渲染該組件的對(duì)應(yīng)路由被 confirm 前調(diào)用
? ? // 不袜匿!能!獲取組件實(shí)例 `this`
? ? // 因?yàn)楫?dāng)守衛(wèi)執(zhí)行前毁涉,組件實(shí)例還沒被創(chuàng)建
? },
? beforeRouteLeave (to, from, next) { 后置
? ? // 導(dǎo)航離開該組件的對(duì)應(yīng)路由時(shí)調(diào)用
? ? // 可以訪問組件實(shí)例 `this`
? }
}
10.vue的優(yōu)化
不支持低版本的瀏覽器沉帮,最低只支持到IE9锈死;不利于SEO的優(yōu)化(如果要支持SEO贫堰,建議通過服務(wù)端來進(jìn)行渲染組件)穆壕;第一次加載首頁耗時(shí)相對(duì)長一些;不可以使用瀏覽器的導(dǎo)航按鈕需要自行實(shí)現(xiàn)前進(jìn)其屏、后退
11.什么是插槽或內(nèi)容分發(fā) 喇勋,插槽有幾種方式
組件內(nèi)部保留槽位:
具名槽位:<slot name=槽名
匿名槽位: <slot></..>
調(diào)用組件插入內(nèi)容:? 內(nèi)容 == dom | 組件
<組件名>
<template #槽名> 內(nèi)容 | <組件名>
<template v-slot:槽名>內(nèi)容
父級(jí)模板里的所有內(nèi)容都是在父級(jí)作用域中編譯的;子模板里的所有內(nèi)容都是在子作用域中編譯
12.簡述下mvvm和MVC
MVC:
1.View 傳送指令到 Controller
2.Controller 完成業(yè)務(wù)邏輯后偎行,要求 Model 改變狀態(tài)
3.Model 將新的數(shù)據(jù)發(fā)送到 View川背,用戶得到反饋
MVP:
1. 各部分之間的通信,都是雙向的蛤袒。
2. View 與 Model 不發(fā)生聯(lián)系熄云,都通過 Presenter 傳遞。
3. View 非常薄妙真,不部署任何業(yè)務(wù)邏輯缴允,稱為"被動(dòng)視圖"(Passive View),即沒有任何主動(dòng)性珍德,而 Presenter非常厚练般,所有邏輯都部署在那里。
MVVM:
和MVP很像锈候,采用雙向綁定(data-binding):View的變動(dòng)薄料,自動(dòng)反映在 ViewModel,反之亦然
13.路由懶加載泵琳,異步路由摄职,分片打包
原理: 把組件封裝到一個(gè)函數(shù)內(nèi)部,路由激活時(shí)虑稼,調(diào)用該函數(shù)琳钉,函數(shù)內(nèi)部 異步加載目標(biāo)組件并返回
路由配置router.js:
a)
- import home from "../components/home.vue"
+ const home =()=>import("../components/home.vue");
{path:'/home', component: home }
b)
{path:xxx, component: r => { require(['./login/Login'], r) }}
15.vue的數(shù)據(jù)是響應(yīng)式的,請問什么時(shí)候是非響應(yīng)式的并如何解決
a:數(shù)組數(shù)據(jù):
問題1:通過改變長度蛛倦,利用索引直接設(shè)置跟項(xiàng)
解決:Vue.set(數(shù)組對(duì)象, key, value)??????????????????????? | ? ? ? ? ? ? ?? vm|this.$set(數(shù)組對(duì)象, key, value)
問題2:對(duì)數(shù)組使用了非變異 (non-mutating method) 方法(返回的了新數(shù)組)
解決:對(duì)象合并
對(duì)象數(shù)據(jù)變化:
問題:問題:data:{a:1}歌懒;a 數(shù)據(jù)是響應(yīng)式的;vm.b='qq';? b 屬性不是響應(yīng)式的
解決:Vue.set(對(duì)象, key, value)??????????????????????????? |??????????????????????????? vm|this.$set(對(duì)象, key, value)
總結(jié):數(shù)據(jù)一開始就應(yīng)該出現(xiàn)在data里溯壶,數(shù)組里面永遠(yuǎn)不要放置簡單性數(shù)據(jù)
16.如何編寫一個(gè)自定義指令
指令是個(gè)函數(shù)或者對(duì)象及皂,用來操作dom橙喘,指令內(nèi)部的this指向window裸诽;
a:全局指令? Vue.directive(指令名稱不帶v-,回調(diào)(el,bingding))
el:dom元素;binding是個(gè)對(duì)象色瘩,含有傳入的參數(shù)又跛,binding碍拆。value
b:局部? 定義在選項(xiàng)里面
directives:{
指令名不帶v- : 函數(shù)(el,binding){}
}
17.如何自定義事件
定義:vm.$on( '自定義事件名'|['自定義事件名1','自定義事件名2'], 回調(diào)(參數(shù)) )
銷毀:vm.$off( '自定義事件名'|['自定義事件名1','自定義事件名2'], 回調(diào)(參數(shù)) )
觸發(fā): vm.$emit(自定義事件名1,參數(shù))
自定義事件名: 使用 kebab-case 的事件名
場景: 在一個(gè)組件實(shí)例上手動(dòng)偵聽事件時(shí)
18.懶加載,按需加載,點(diǎn)擊加載感混,滑動(dòng)加載
把組件加載封裝在一個(gè)函數(shù)中端幼,路由激活的時(shí)候調(diào)用這個(gè)函數(shù),這個(gè)函數(shù)在運(yùn)行的時(shí)候去加載這個(gè)組件弧满。加載用import或者requireAPI
19.如何更改計(jì)算屬性并響應(yīng)式
計(jì)算屬性的set方法
20.vue的diff算法
突然發(fā)現(xiàn)弄懂這個(gè)就不是初級(jí)了婆跑。。庭呜。
https://juejin.im/post/5c97002b6fb9a070aa5cf60b
21.虛擬dom
1.什么是虛擬dom
是真實(shí)dom的一種抽象滑进,虛擬dom的節(jié)點(diǎn)和真實(shí)dom的節(jié)點(diǎn)一一對(duì)應(yīng),最終通過一系列操作講虛擬dom映射到真實(shí)dom上募谎。
2.虛擬dom性能作用
因?yàn)樘摂Mdom在渲染的時(shí)候會(huì)和上一次渲染到真實(shí)dom的虛擬節(jié)點(diǎn)進(jìn)行比對(duì)扶关,比如說一個(gè)UL中有多個(gè)LI,但只有一個(gè)LI發(fā)生變化数冬,所以進(jìn)行比對(duì)后就只會(huì)渲染變化的LI驮审。虛擬dom在Vue中主要做了2件事情:提供和真實(shí)dom節(jié)點(diǎn)所對(duì)應(yīng)的虛擬dom節(jié)點(diǎn);將虛擬節(jié)點(diǎn)vnode和舊虛擬節(jié)點(diǎn)oldVnode進(jìn)行對(duì)比吉执,然后更新視圖
3.為什么虛擬dom性能高
a:虛擬dom以js對(duì)象為基礎(chǔ)疯淫,不依賴真實(shí)平臺(tái)環(huán)境,所以具備跨平臺(tái)能力戳玫,比如瀏覽器平臺(tái)熙掺、Weex、Node 等
b:操作dom慢咕宿,js運(yùn)行效率高币绩,可以將dom比對(duì)操作放在js層,提高效率府阀,虛擬dom實(shí)質(zhì)是js和dom之間做一個(gè)緩存缆镣,既然js操作都沒慢,那我就操作虛擬dom,虛擬dom內(nèi)部可以給我做優(yōu)化對(duì)比试浙,將變化的部分董瞻,更新視圖
c:可以提高渲染性能,但并不是單次的操作田巴,而是大量的頻繁的數(shù)據(jù)更新下钠糊,能夠?qū)σ晥D進(jìn)行合理、高效的更新壹哺。為了實(shí)現(xiàn)高效的DOM操作抄伍,一套高效的虛擬DOM diff算法顯得很有必要。我們通過patch 的核心----diff 算法管宵,找出本次DOM需要更新的節(jié)點(diǎn)來更新截珍,其他的不更新攀甚。
2個(gè)主要的函數(shù)
patch(container,vnode) :初次渲染的時(shí)候,將VDOM渲染成真正的DOM然后插入到容器里面岗喉。
patch(vnode,newVnode):再次渲染的時(shí)候云稚,將新的vnode和舊的vnode相對(duì)比,然后之間差異應(yīng)用到所構(gòu)建的真正的DOM樹上沈堡。