摘要:用創(chuàng)建好的實(shí)例調(diào)用守衛(wèi)中傳給的回調(diào)函數(shù)。注冊一個(gè)全局守衛(wèi)。這和類似,區(qū)別是在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調(diào)用僅代表個(gè)人見解,能力有限,如有錯誤會誤人子弟的地方歡迎留言指出謝謝
原文地址
vue(前端框架)解決了什么問題?現(xiàn)在的前端頁面元素越來越多,結(jié)構(gòu)也變得越來越復(fù)雜,當(dāng)數(shù)據(jù)和視圖混合在一起的時(shí)候?qū)λ鼈兊奶幚頃謴?fù)雜,同時(shí)也很容易出現(xiàn)錯誤,而現(xiàn)代框架使用聲明式語法,描述組件對象的嵌套關(guān)系,并自動生成與dom對象的對應(yīng)關(guān)系
參考1
vue生命周期 | 描述 |
---|---|
beforeCreate | 組件實(shí)力被創(chuàng)建,el和數(shù)據(jù)對象都為undefined,還未初始化 |
create | 數(shù)據(jù)已經(jīng)被初始化,并且初始化了Vue內(nèi)部事件,但是DOM還未生成 |
befroeMount | 完成了模板的編譯。把data對象里面的數(shù)據(jù)和vue的語法寫的模板編譯成了虛擬DOM |
mouted | 執(zhí)行了render函數(shù),將渲染出來的內(nèi)容掛載到了DOM節(jié)點(diǎn)上 |
beforeUpdate | 組件更新之前:數(shù)據(jù)發(fā)生變化時(shí),會調(diào)用beforeUpdate,然后經(jīng)歷DOM diff |
updated | 組件更新后 |
actived | keep-alive組件被激活 |
deactivated | keep-alive移除 |
beforeDestroy | 組件銷毀前 |
destroyed | 組件銷毀后 |
可以問數(shù)據(jù)變動如何和視圖聯(lián)系在一起?
Vue是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式, Vue相應(yīng)系統(tǒng)有三大核心:observe,dep,watcher;精簡版Vue代碼參考
Observe:當(dāng)一個(gè)Vue實(shí)例創(chuàng)建時(shí),initData階段,vue會遍歷data選項(xiàng)的屬性(observe),用 Object.defineProperty 將它們轉(zhuǎn)為 getter/setter并且在內(nèi)部追蹤相關(guān)依賴(dep),在屬性被訪問和修改時(shí)通知變化。
Compite:調(diào)用compile方法解析模版,當(dāng)視圖中有用到vue.data中數(shù)據(jù)的時(shí)候,會調(diào)用實(shí)例化watcher方法進(jìn)行依賴收集
Watcher:是Observer和Compile之間通信的橋梁,當(dāng)視圖中遇到綁定的數(shù)據(jù)時(shí),在watcher方法中會獲取這個(gè)數(shù)據(jù),此時(shí)會觸發(fā)observe中的getter方法,
Dep:發(fā)布訂閱模式,observe中數(shù)據(jù)的getter被觸發(fā)時(shí)會收集依賴的watcher(dep.depend方法)
當(dāng)有數(shù)據(jù)被改動時(shí)會觸發(fā)observe中數(shù)據(jù)的setter,此時(shí)會調(diào)用dep.notify方法給所有訂閱的watcher發(fā)通知(通過回掉方式)進(jìn)行視圖更新,此時(shí)會進(jìn)行diff流程:
vue中data為什么必須要是一個(gè)函數(shù)vue中的data為對象,是引用類型,當(dāng)重用組件時(shí),一個(gè)組件對data做了更改,那么另一個(gè)組件也會跟著改,而使用返回一個(gè)函數(shù)返回?cái)?shù)據(jù),則每次返回都是一個(gè)新對象,引用地址不用,所以就不會出現(xiàn)問題Virtual DOM 是什么
虛擬DOM是一個(gè)JavaScript對象,包含了當(dāng)前DOM的基本結(jié)構(gòu)和信息,它的存在是為了減少對操作無用DOM所帶來的性能消耗,在大量的、頻繁的數(shù)據(jù)更新下能夠?qū)σ晥D進(jìn)行合理的高效的更新(細(xì)粒度的精準(zhǔn)修改),同時(shí)也抽象了原來的渲染過程,實(shí)現(xiàn)了跨平臺的能力
簡述vue中的DOM DIFF算法精簡源碼;當(dāng)數(shù)據(jù)發(fā)生改變時(shí),set方法會讓調(diào)用Dep.notify通知所有訂閱者Watcher,訂閱者就會調(diào)用patch給真實(shí)的DOM打補(bǔ)丁(兩個(gè)重要函數(shù)patchVnode和updateChildren):
先判斷根結(jié)點(diǎn)及變化后的節(jié)點(diǎn)是否是sameVnode,如果不是的化,就會創(chuàng)建新的根結(jié)點(diǎn)并進(jìn)行替換
如果是sameVnode,則進(jìn)入patchVnode函數(shù),其基本判斷
如果兩個(gè)節(jié)點(diǎn)是相等oldVnode === vnode則直接return
如果新節(jié)點(diǎn)是文本節(jié)點(diǎn),則判斷新舊文本節(jié)點(diǎn)是否一致,不一致(oldVnode.text !== vnode.text)則替換
如果新節(jié)點(diǎn)不是文本節(jié)點(diǎn),則開始比較新舊節(jié)點(diǎn)的子節(jié)點(diǎn)oldCh和ch:
如果子節(jié)點(diǎn)都存在,則進(jìn)行updateChildren計(jì)算(稍后講)
如果只有新子節(jié)點(diǎn)存在,則如果舊節(jié)點(diǎn)有文本節(jié)點(diǎn),則移除文本節(jié)點(diǎn),然后將新子節(jié)點(diǎn)拆入
如果只有舊子節(jié)點(diǎn)存在,則移除所有子節(jié)點(diǎn)
如果均無子節(jié)點(diǎn)且舊節(jié)點(diǎn)是文本節(jié)點(diǎn),則移除文本節(jié)點(diǎn)(此時(shí)新節(jié)點(diǎn)一定不是文本節(jié)點(diǎn))
updateChildren函數(shù)做細(xì)致對比
start && oldStart對比
end && oldEnd對比
start && oldEnd對比
end && oldStart 對比
生成map映射,(key:舊子節(jié)點(diǎn)上的key,value:舊子節(jié)點(diǎn)在自己點(diǎn)中的位置),根據(jù)key記錄下老節(jié)點(diǎn)在新節(jié)點(diǎn)的位置(idxInOld)
1) 如果找到了idxInOld,如果是相同節(jié)點(diǎn)則移動舊節(jié)點(diǎn)到新的對應(yīng)的地方,否則雖然key相同但元素不同,當(dāng)作新元素節(jié)點(diǎn)去創(chuàng)建
2) 如果沒有找到idxInOld,則創(chuàng)建節(jié)點(diǎn)
如果老節(jié)點(diǎn)先遍歷完,則新節(jié)點(diǎn)比老節(jié)點(diǎn)多,將新節(jié)點(diǎn)多余的插入進(jìn)去
如果新節(jié)點(diǎn)先遍歷完,則就節(jié)點(diǎn)比新節(jié)點(diǎn)多,將舊節(jié)點(diǎn)多余的刪除
vue中key的作用主要是為了復(fù)用節(jié)點(diǎn),高效的更新虛擬DOM,另外,在使用標(biāo)簽元素過渡效果時(shí)也會用到key
computed的原理vue對象初始化的同時(shí)對計(jì)算屬性進(jìn)行初始化initComputed,
computed會對初始化的Watcher傳入lazy: true就會觸發(fā)Watcher中的watcher.dirty=true(dirty決定了當(dāng)前屬性是否更新),
當(dāng)視圖中有對computed引用的時(shí)候會第一次執(zhí)行計(jì)算屬性,并將dirty設(shè)置為false,并將結(jié)果保存在this.value中進(jìn)行緩存,
如果依賴沒有更改,則下次獲取computed會這直接返回this.value,只有當(dāng)computed所依賴的屬性發(fā)生變化時(shí)會將dirty設(shè)置為true,并重新計(jì)算
class Watcher{ …… evaluate () { this.value = this.get() this.dirty = false } …… } class initComputed{ …… //計(jì)算屬性的getter 獲取計(jì)算屬性的值時(shí)會調(diào)用 createComputedGetter (key) { return function computedGetter () { //獲取到相應(yīng)的watcher const watcher = this._computedWatchers && this._computedWatchers[key] if (watcher) { //watcher.dirty 參數(shù)決定了計(jì)算屬性值是否需要重新計(jì)算,默認(rèn)值為true,即第一次時(shí)會調(diào)用一次 if (watcher.dirty) { /*每次執(zhí)行之后watcher.dirty會設(shè)置為false,只要依賴的data值改變時(shí)才會觸發(fā) watcher.dirty為true,從而獲取值時(shí)從新計(jì)算*/ watcher.evaluate() } //獲取依賴 if (Dep.target) { watcher.depend() } //返回計(jì)算屬性的值 return watcher.value } } } …… }計(jì)算屬性computed和watch的區(qū)別
計(jì)算屬性顧名思義就是通過其他變量計(jì)算得來的,它的值是基于其所依賴的屬性來進(jìn)行緩存的,只有在其所依賴的屬性發(fā)生變化時(shí)才會從新求值
watch是監(jiān)聽一個(gè)變量,當(dāng)變量發(fā)生變化時(shí),會調(diào)用對應(yīng)的方法
vue實(shí)現(xiàn)響應(yīng)式并不是數(shù)據(jù)一更新就立刻觸發(fā)dom變化,而是按照一定的策略對dom進(jìn)行更新,源碼位置,原理:
首先會將所有的nextTick放到一個(gè)函數(shù)中,然后放在callbacks數(shù)組中,$nextTick沒有傳cb回掉,則返回一個(gè)promise
接下來就是callbacks的執(zhí)行時(shí)機(jī)
首先如果瀏覽器是否兼容promise,則用promise.resolve().then來執(zhí)行callbacks
如果瀏覽器兼容MutationObserver,則用實(shí)例化的MutationObserver監(jiān)聽文本變化來執(zhí)行回掉,
如果兼容setImmediate,則用setImmediate(cb)來執(zhí)行回掉
最后降級為用setTimeout(fn,0)來執(zhí)行
在vue2.5.X版本中對于像v-on這樣的DOM交互事件,默認(rèn)走macroTimerFunc,也就是,跳過第一步promise的判斷,
子組件為何不可以修改父組件傳遞的 Prop,是如何監(jiān)控并給出錯誤提示的單向數(shù)據(jù)流,易于監(jiān)測數(shù)據(jù)的流動,出現(xiàn)了錯誤可以更加迅速的定位到錯誤發(fā)生的位置
在initProps時(shí),會對props進(jìn)行defineReactive操作,傳入的第四個(gè)參數(shù)是自定義的set報(bào)錯判斷函數(shù),該函數(shù)會在觸發(fā)props的set方法時(shí)執(zhí)行
// src/core/instance/state.js 源碼路徑 function initProps (vm: Component, propsOptions: Object) { ... for (const key in propsOptions) { if (process.env.NODE_ENV !== "production") { ... defineReactive(props, key, value, () => { // 如果不是跟元素并且不是更新子元素 if (!isRoot && !isUpdatingChildComponent) { warn( `Avoid mutating a prop directly since the value will be ` + `overwritten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop"s ` + `value. Prop being mutated: "${key}"`, vm ) } })} ... } } // src/core/observer/index.js export function defineReactive (obj,key,val,customSetter,shallow) { const property = Object.getOwnPropertyDescriptor(obj, key) const getter = property && property.get const setter = property && property.set Object.defineProperty(obj, key, { ... set: function reactiveSetter (newVal) { const value = getter ? getter.call(obj) : val if (newVal === value || (newVal !== newVal && value !== value)) { return } if (process.env.NODE_ENV !== "production" && customSetter) { customSetter() } if (getter && !setter) return if (setter) { setter.call(obj, newVal) } else { val = newVal } childOb = !shallow && observe(newVal) dep.notify() } }) }父子組件的生命周期執(zhí)行順序
加載過程:父組件beforeCreate => 父組件created => 父組件beforeMount => 子組件beforeCreate => 子組件created => 子組件 beforeMount => 子組件mounted => 父組件mounted
更新過程:父組件beforeUpdate => 子組件beforeUpdate => 子組件updated => 父組件updated
銷毀過程:父組件beforeDestroy => 子組件 beforeDestroy => 子組件 destoryed => 父組件 destoryed
官網(wǎng)
導(dǎo)航被觸發(fā)。
在失活的組件里調(diào)用離開守衛(wèi)。
調(diào)用全局的 beforeEach 守衛(wèi)。
在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi) (2.2+)。
在路由配置里調(diào)用 beforeEnter。
解析異步路由組件。
在被激活的組件里調(diào)用 beforeRouteEnter。
調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)。
導(dǎo)航被確認(rèn)。
調(diào)用全局的 afterEach 鉤子。
觸發(fā) DOM 更新。
用創(chuàng)建好的實(shí)例調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)。
router.beforeResolve 注冊一個(gè)全局守衛(wèi)。這和 router.beforeEach 類似,區(qū)別是在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調(diào)用
僅代表個(gè)人見解,能力有限,如有錯誤會誤人子弟的地方歡迎留言指出;謝謝文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105599.html
摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號作者架構(gòu)師奮斗者掃描主頁左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...
摘要:前言用有一段時(shí)間了,從用搭建項(xiàng)目一步步配置,到之后的研究動效這些,一直想寫些東西記錄一下做個(gè)總結(jié),剛好趁著有空就整理一下。結(jié)語有新的知識點(diǎn)會更新到知識體系中,總結(jié)和心得體會會單獨(dú)寫文章詳述,努力填坑 前言 用vue有一段時(shí)間了,從用vue-cli搭建項(xiàng)目、一步步配置axios、vuex、vue-router,到之后的研究canvas、動效這些,一直想寫些東西記錄一下、做個(gè)總結(jié),剛好趁著...
摘要:前言本文主要總結(jié)了自己實(shí)際開發(fā)項(xiàng)目當(dāng)中遇到的一些常見問題以及解決方案組件的是當(dāng)一個(gè)組件被定義,必須聲明為返回一個(gè)初始數(shù)據(jù)對象的函數(shù),因?yàn)榻M件可能被用來創(chuàng)建多個(gè)實(shí)例。實(shí)在要比較只能比較對象的具體值了。 前言 本文主要總結(jié)了自己vue實(shí)際開發(fā)項(xiàng)目當(dāng)中遇到的一些常見問題以及解決方案 VUE組件的data是function 當(dāng)一個(gè)組件被定義,data?必須聲明為返回一個(gè)初始數(shù)據(jù)對象的函數(shù),因?yàn)?..
摘要:本文只是對官方文檔和對官方的個(gè)人學(xué)習(xí)總結(jié),說得不夠完整的請見諒本文主要對以下幾方面內(nèi)容對的內(nèi)容進(jìn)行分析總結(jié)出現(xiàn)的原因的總體原理當(dāng)中的數(shù)據(jù)預(yù)取在編寫代碼時(shí)候的限制的構(gòu)建原理出現(xiàn)的原因單頁應(yīng)用有一個(gè)很大的缺點(diǎn)就是問題,搜索引擎目前只能對同步的進(jìn) 本文只是對Vue.js官方SSR文檔和對官方hackernews demo的個(gè)人學(xué)習(xí)總結(jié),說得不夠完整的請見諒 本文主要對以下幾方面內(nèi)容對Vue....
摘要:天王蓋地虎鉤子事件得到的結(jié)果是小總結(jié)實(shí)例創(chuàng)建完成后,我們能讀取到數(shù)據(jù)的值,但是還沒生成,掛載屬性還不存在。此時(shí)的階段解讀為掛載完畢階段我們再打印下此時(shí)看看鉤子事件得到的結(jié)果是可見,已經(jīng)成功渲染成里面對應(yīng)的值天王蓋地虎了。 你不需要立馬弄明白所有的東西,不過隨著你的不斷學(xué)習(xí)和使用,它的參考價(jià)值會越來越高。 現(xiàn)在項(xiàng)目中遇到了,好好回頭總結(jié)一波Vue生命周期,以后用到的時(shí)候再來翻翻。 啥叫V...
摘要:寫在前面其實(shí)最開始不是特意來研究的源碼,只是想了解下的命令,如果想要了解命令的話,那么繞不開寫的。通過分析發(fā)現(xiàn)與相比,變化太大了,通過引入插件系統(tǒng),可以讓開發(fā)者利用其暴露的對項(xiàng)目進(jìn)行擴(kuò)展。 showImg(https://segmentfault.com/img/bVboijb?w=1600&h=1094); 寫在前面 其實(shí)最開始不是特意來研究 vue-cli 的源碼,只是想了解下 n...
閱讀 2514·2021-09-09 09:33
閱讀 2876·2019-08-30 15:56
閱讀 3159·2019-08-30 14:21
閱讀 911·2019-08-30 13:01
閱讀 874·2019-08-26 18:27
閱讀 3594·2019-08-26 13:47
閱讀 3465·2019-08-26 10:26
閱讀 1597·2019-08-23 18:38