目錄
2.v-if、v-show區(qū)別
3.vue-router 有哪些模式? 區(qū)別是什么? 具體是怎么實(shí)現(xiàn)的
14.diff算法
自定義指令(v-check瓜客、 v-focus)的方法有哪些?它有哪些鉤子函數(shù)?
1.深入淺出Vue響應(yīng)式原理
2.v-if拦止、v-show區(qū)別
3.vue-router 有哪些模式? 區(qū)別是什么? 具體是怎么實(shí)現(xiàn)的
淺談vue-router原理
https://www.cnblogs.com/goloving/p/9147551.html
https://blog.csdn.net/wang1006008051/article/details/81805932
history和hash的區(qū)別
- hash路由在地址欄URL上有#县遣,用 window.location.hash 讀取。而history路由沒(méi)有會(huì)好看一點(diǎn)
- 我們進(jìn)行回車(chē)刷新操作汹族,hash路由會(huì)加載到地址欄對(duì)應(yīng)的頁(yè)面萧求,而history路由一般就404報(bào)錯(cuò)了(刷新是網(wǎng)絡(luò)請(qǐng)求,沒(méi)有后端準(zhǔn)備時(shí)會(huì)報(bào)錯(cuò))顶瞒。
- hash路由支持低版本的瀏覽器夸政,而history路由是HTML5新增的API。
4.hash的特點(diǎn)在于它雖然出現(xiàn)在了URL中搁拙,但是不包括在http請(qǐng)求中秒梳,所以對(duì)于后端是沒(méi)有一點(diǎn)影響的,所以改變hash不會(huì)重新加載頁(yè)面箕速,所以這也是單頁(yè)面應(yīng)用的必備酪碘。
5.history運(yùn)用了瀏覽器的歷史記錄棧,之前有back,forward,go方法盐茎,之后在HTML5中新增了pushState()和replaceState()方法兴垦,它們提供了對(duì)歷史記錄進(jìn)行修改的功能,不過(guò)在進(jìn)行修改時(shí)字柠,雖然改變了當(dāng)前的URL探越,但是瀏覽器不會(huì)馬上向后端發(fā)送請(qǐng)求。
6.history的這種模式需要后臺(tái)配置支持窑业。比如:當(dāng)我們進(jìn)行項(xiàng)目的主頁(yè)的時(shí)候钦幔,一切正常,可以訪問(wèn)常柄,但是當(dāng)我們刷新頁(yè)面或者直接訪問(wèn)路徑的時(shí)候就會(huì)返回404鲤氢,那是因?yàn)樵趆istory模式下,只是動(dòng)態(tài)的通過(guò)js操作window.history來(lái)改變?yōu)g覽器地址欄里的路徑西潘,并沒(méi)有發(fā)起http請(qǐng)求卷玉,但是當(dāng)我直接在瀏覽器里輸入這個(gè)地址的時(shí)候,就一定要對(duì)服務(wù)器發(fā)起http請(qǐng)求喷市,但是這個(gè)目標(biāo)在服務(wù)器上又不存在相种,所以會(huì)返回404
總結(jié)
當(dāng)然啦,history 也不是樣樣都好品姓。SPA 雖然在瀏覽器里游刃有余寝并,但真要通過(guò) URL 向后端發(fā)起 HTTP 請(qǐng)求時(shí),兩者的差異就來(lái)了缭黔。尤其在用戶(hù)手動(dòng)輸入 URL 后回車(chē)食茎,或者刷新(重啟)瀏覽器的時(shí)候。
- hash 模式下馏谨,僅 hash 符號(hào)之前的內(nèi)容會(huì)被包含在請(qǐng)求中别渔,如 http://www.abc.com,因此對(duì)于后端來(lái)說(shuō)惧互,即使沒(méi)有做到對(duì)路由的全覆蓋哎媚,也不會(huì)返回 404 錯(cuò)誤。
- history 模式下喊儡,前端的 URL 必須和實(shí)際向后端發(fā)起請(qǐng)求的 URL 一致拨与,如 http://www.abc.com/book/id。如果后端缺少對(duì) /book/id 的路由處理艾猜,將返回 404 錯(cuò)誤买喧。Vue-Router 官網(wǎng)里如此描述:“不過(guò)這種模式要玩好捻悯,還需要后臺(tái)配置支持……所以呢,你要在服務(wù)端增加一個(gè)覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源淤毛,則應(yīng)該返回同一個(gè) index.html 頁(yè)面今缚,這個(gè)頁(yè)面就是你 app 依賴(lài)的頁(yè)面〉偷”
- 結(jié)合自身例子姓言,對(duì)于一般的 Vue + Vue-Router + Webpack + XXX 形式的 Web 開(kāi)發(fā)場(chǎng)景,用 history 模式即可蔗蹋,只需在后端(Apache 或 Nginx)進(jìn)行簡(jiǎn)單的路由配置何荚,同時(shí)搭配前端路由的 404 頁(yè)面支持。
4. vue-router導(dǎo)航守衛(wèi)
https://zhuanlan.zhihu.com/p/54112006
應(yīng)用場(chǎng)景
https://www.cnblogs.com/baifangzi/p/14283463.html
5. vue組件通信
6. diff算法
7. Vue3 proxy
8. vue.$set
原理
https://www.jb51.net/article/146580.htm
源碼
export function set (target: Array<any> | Object, key: any, val: any): any {
if (process.env.NODE_ENV !== 'production' &&
(isUndef(target) || isPrimitive(target))
) {
warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
} // 判斷目標(biāo)值是否為數(shù)組猪杭,并且key值是否為有效的數(shù)組索引
if (Array.isArray(target) && isValidArrayIndex(key)) { // 對(duì)比數(shù)組的key值和數(shù)組長(zhǎng)度规求,取較大值設(shè)置為數(shù)組的長(zhǎng)度
target.length = Math.max(target.length, key) // 替換目標(biāo)值
target.splice(key, 1, val)
return val
} // 如果目標(biāo)值是對(duì)象蝶糯,并且key值是目標(biāo)值存在的有效key值诈闺,并且不是原型上的key值
if (key in target && !(key in Object.prototype)) { // 直接更改目標(biāo)值
target[key] = val
return val
}
const ob = (target: any).__ob__ // 判斷目標(biāo)值是否為響應(yīng)式的
if (target._isVue || (ob && ob.vmCount)) { // 如果是vue根實(shí)例菜枷,就警告
process.env.NODE_ENV !== 'production' && warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
)
return val
}
if (!ob) { // 如果目標(biāo)值不是響應(yīng)式的,那么值需要給對(duì)應(yīng)的key賦值
target[key] = val
return val
} // 其他情況涮较,目標(biāo)值是響應(yīng)式的稠鼻,就通過(guò)Object.defineProperty進(jìn)行數(shù)據(jù)監(jiān)聽(tīng)
defineReactive(ob.value, key, val) // 通知更新dom操作
ob.dep.notify()
return val
}
大概流程
判斷目標(biāo)值是否為有效值,不是有效值直接停止
判斷是否為數(shù)組狂票,并且key值是否為有效的key值
如果是數(shù)組候齿,就選擇數(shù)組的長(zhǎng)度和key值取較大值作為數(shù)組的新的length值,并且替換目標(biāo)值splice方法闺属,重寫(xiě)了慌盯,所以執(zhí)行splice,會(huì)雙向數(shù)據(jù)綁定判斷目標(biāo)值是否為響應(yīng)式的ob
如果是vue實(shí)例掂器,直接不行
如果不是響應(yīng)式的數(shù)據(jù)亚皂,就是普通的修改對(duì)象操作
如果是響應(yīng)式數(shù)據(jù),那就通過(guò)Object.defineProperty進(jìn)行數(shù)據(jù)劫持通知dom更新
9. Vue是怎么重寫(xiě)數(shù)組的
// 緩存數(shù)組原型
const arrayProto = Array.prototype;
// 實(shí)現(xiàn) arrayMethods.__proto__ === Array.prototype
export const arrayMethods = Object.create(arrayProto);
// 需要進(jìn)行功能拓展的方法
const methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse"
];
/**
* Intercept mutating methods and emit events
*/
methodsToPatch.forEach(function(method) {
// 緩存原生數(shù)組方法
const original = arrayProto[method];
def(arrayMethods, method, function mutator(...args) {
// 執(zhí)行并緩存原生數(shù)組功能
const result = original.apply(this, args);
// 響應(yīng)式處理
const ob = this.__ob__;
let inserted;
switch (method) {
// push国瓮、unshift會(huì)新增索引灭必,所以要手動(dòng)observer
case "push":
case "unshift":
inserted = args;
break;
// splice方法,如果傳入了第三個(gè)參數(shù)乃摹,也會(huì)有索引加入禁漓,也要手動(dòng)observer。
case "splice":
inserted = args.slice(2);
break;
}
//
if (inserted) ob.observeArray(inserted);// 獲取插入的值孵睬,并設(shè)置響應(yīng)式監(jiān)聽(tīng)
// notify change
ob.dep.notify();// 通知依賴(lài)更新
// 返回原生數(shù)組方法的執(zhí)行結(jié)果
return result;
});
});
};
10. Vue.nextTick()
實(shí)現(xiàn)原理
/* @flow */
/* globals MutationObserver */
import { noop } from 'shared/util'
import { handleError } from './error'
import { isIE, isIOS, isNative } from './env'
export let isUsingMicroTask = false
const callbacks = []
let pending = false
/**
* 對(duì)所有callback進(jìn)行遍歷播歼,然后指向響應(yīng)的回調(diào)函數(shù)
* 使用 callbacks保證了可以在同一個(gè)tick內(nèi)執(zhí)行多次 nextTick,不會(huì)開(kāi)啟多個(gè)異步任務(wù)掰读,而把這些異步任務(wù)都?jí)撼梢粋€(gè)同步任務(wù)秘狞,在下一個(gè) tick 執(zhí)行完畢叭莫。
*/
function flushCallbacks () {
pending = false
const copies = callbacks.slice(0)
callbacks.length = 0
for (let i = 0; i < copies.length; i++) {
copies[i]( "i")
}
}
let timerFunc
/*
* timerFunc 實(shí)現(xiàn)的就是根據(jù)當(dāng)前環(huán)境判斷使用哪種方式實(shí)現(xiàn)
* 就是按照 Promise.then和 MutationObserver以及setImmediate的優(yōu)先級(jí)來(lái)判斷,支持哪個(gè)就用哪個(gè)烁试,如果執(zhí)行環(huán)境不支持食寡,會(huì)采用setTimeout(fn, 0)代替;
*/
// 判斷是否支持原生 Promise
if (typeof Promise !== 'undefined' && isNative(Promise)) {
const p = Promise.resolve()
timerFunc = () => {
p.then(flushCallbacks)
if (isIOS) setTimeout(noop)
}
isUsingMicroTask = true
// 不支持 Promise的話(huà)廓潜,再判斷是否原生支持 MutationObserver
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
isNative(MutationObserver) ||
// PhantomJS and iOS 7.x
MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
// 新建一個(gè) textNode的DOM對(duì)象,使用 MutationObserver 綁定該DOM并傳入回調(diào)函數(shù)善榛,在DOM發(fā)生變化的時(shí)候會(huì)觸發(fā)回調(diào)辩蛋,該回調(diào)會(huì)進(jìn)入主線(xiàn)程(比任務(wù)隊(duì)列優(yōu)先執(zhí)行)
let counter = 1
const observer = new MutationObserver(flushCallbacks)
const textNode = document.createTextNode(String(counter))
observer.observe(textNode, {
characterData: true
})
timerFunc = () => {
counter = (counter + 1) % 2
// 此時(shí)便會(huì)觸發(fā)回調(diào)
textNode.data = String(counter)
}
isUsingMicroTask = true
// 不支持的 MutationObserver 的話(huà),再去判斷是否原生支持 setImmediate
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
timerFunc = () => {
setImmediate(flushCallbacks)
}
} else {
// Promise移盆,MutationObserver, setImmediate 都不支持的話(huà)悼院,最后使用 setTimeout(fun, 0)
timerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
// 該函數(shù)的作用就是延遲 cb 到當(dāng)前調(diào)用棧執(zhí)行完成之后執(zhí)行
export function nextTick (cb?: Function, ctx?: Object) {
// 傳入的回調(diào)函數(shù)會(huì)在callbacks中存起來(lái)
let _resolve
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, 'nextTick')
}
} else if (_resolve) {
_resolve(ctx)
}
})
// pending是一個(gè)狀態(tài)標(biāo)記,保證timerFunc在下一個(gè)tick之前只執(zhí)行一次
if (!pending) {
pending = true
/**
* timerFunc 實(shí)現(xiàn)的就是根據(jù)當(dāng)前環(huán)境判斷使用哪種方式實(shí)現(xiàn)
* 就是按照 Promise.then和 MutationObserver以及setImmediate的優(yōu)先級(jí)來(lái)判斷咒循,支持哪個(gè)就用哪個(gè)据途,如果執(zhí)行環(huán)境不支持,會(huì)采用setTimeout(fn, 0)代替叙甸;
*/
timerFunc()
}
// 當(dāng)nextTick不傳參數(shù)的時(shí)候颖医,提供一個(gè)Promise化的調(diào)用
// $flow-disable-line
if (!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
}
- nextTick接受一個(gè)回調(diào)函數(shù)時(shí)(當(dāng)不傳參數(shù)的時(shí)候,提供一個(gè)Promise化的調(diào)用)裆蒸,傳入的回調(diào)函數(shù)會(huì)在callbacks中存起來(lái)熔萧,根據(jù)一個(gè)狀態(tài)標(biāo)記 pending 來(lái)判斷當(dāng)前是否要執(zhí)行 timerFunc();
- timerFunc() 是根據(jù)當(dāng)前環(huán)境判斷使用哪種方式實(shí)現(xiàn)僚祷,按照 Promise.then和 MutationObserver以及setImmediate的優(yōu)先級(jí)來(lái)判斷佛致,支持哪個(gè)就用哪個(gè),如果執(zhí)行環(huán)境不支持辙谜,會(huì)采用setTimeout(fn, 0)代替俺榆;
- timerFunc()函數(shù)中會(huì)執(zhí)行 flushCallbacks函數(shù),flushCallbacks函數(shù)的作用就是對(duì)所有callback進(jìn)行遍歷装哆,然后指向響應(yīng)的回調(diào)函數(shù)
總體來(lái)說(shuō):就是先判斷是否支持promise罐脊,如果支持promise。就通過(guò)Promise.resolve的方法蜕琴,異步執(zhí)行方法爹殊,如果不支持promise,就判斷是否支持MutationObserver奸绷。如果支持梗夸,就通過(guò)MutationObserver(微異步)來(lái)異步執(zhí)行方法,如果MutationObserver還不支持号醉,就通過(guò)setTimeout來(lái)異步執(zhí)行方法反症。
MutaionObserver通過(guò)創(chuàng)建新的節(jié)點(diǎn)辛块,調(diào)用timerFunc方法,改變MutationObserver監(jiān)聽(tīng)的節(jié)點(diǎn)變化铅碍,從而觸發(fā)異步方法執(zhí)行润绵。
11. Key的作用
12. slot插槽
13. 為什么vue data屬性必須是一個(gè)函數(shù)
14.diff算法
15. vue-router編程式導(dǎo)航
16. vue中輸入框事件的使用——@input、@keyup.enter胞谈、@change尘盼、@blur
17. 自定義指令(v-check、 v-focus)的方法有哪些?它有哪些鉤子函數(shù)?
vue2.0
vue3.0
2.0與3.0主要區(qū)別為3.0的鉤子函數(shù)更全
2.0
bind
:只調(diào)用一次烦绳,指令第一次綁定到元素時(shí)調(diào)用卿捎。在這里可以進(jìn)行一次性的初始化設(shè)置。inserted
:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在径密,但不一定已被插入文檔中)午阵。update
:所在組件的 VNode 更新時(shí)調(diào)用,但是可能發(fā)生在其子 VNode 更新之前享扔。指令的值可能發(fā)生了改變底桂,也可能沒(méi)有。但是你可以通過(guò)比較更新前后的值來(lái)忽略不必要的模板更新 (詳細(xì)的鉤子函數(shù)參數(shù)見(jiàn)下)惧眠。componentUpdated
:指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用籽懦。unbind
:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用氛魁。
3.0
created
:在綁定元素的 attribute 或事件監(jiān)聽(tīng)器被應(yīng)用之前調(diào)用猫十。在指令需要附加須要在普通的 v-on 事件監(jiān)聽(tīng)器前調(diào)用的事件監(jiān)聽(tīng)器時(shí),這很有用呆盖。beforeMount
:當(dāng)指令第一次綁定到元素并且在掛載父組件之前調(diào)用拖云。mounted
:在綁定元素的父組件被掛載后調(diào)用。beforeUpdate
:在更新包含組件的 VNode 之前調(diào)用应又。updated
:在包含組件的 VNode 及其子組件的 VNode 更新后調(diào)用宙项。beforeUnmount
:在卸載綁定元素的父組件之前調(diào)用unmounted
:當(dāng)指令與元素解除綁定且父組件已卸載時(shí),只調(diào)用一次株扛。
18. 自定義組件的v-model
19. vue-router router-link組件的active-class屬性
20. vue- router嵌套路由
21. Vue中computed和method之間有什么不同點(diǎn)
VUE中methods watch和compute的區(qū)別和聯(lián)系
22. 要發(fā)送一個(gè)異步請(qǐng)求尤筐,應(yīng)該放在哪個(gè)生命周期
23. vue和原生js的優(yōu)點(diǎn)分析
24. 如果要新增一個(gè)屬性怎么實(shí)現(xiàn)響應(yīng)式
this.$set(this.data,”key”,value’)
Vue.set(vm.items,2,"ling") : 表示 把vm.items 這個(gè)數(shù)組的下標(biāo)為2 的元素,改為"ling"
Vue.set(vm.person,"age","26")
Vue.set()向響應(yīng)式對(duì)象中添加一個(gè)屬性洞就,并確保這個(gè)新屬性同樣是響應(yīng)式的盆繁,且觸發(fā)視圖更新。它必須用于向響應(yīng)式對(duì)象上添加新屬性旬蟋,因?yàn)?Vue 無(wú)法探測(cè)普通的新增屬性 (比如 this.myObject.newProperty = 'hi')
區(qū)別在于Vue.set()是將set函數(shù)綁定在Vue構(gòu)造函數(shù)上油昂,this.$set()是將set函數(shù)綁定在Vue原型上。
Vue.set數(shù)組實(shí)現(xiàn)的原理:其實(shí)Vue.set()對(duì)于數(shù)組的處理其實(shí)就是調(diào)用了splice方法