vue實(shí)現(xiàn)數(shù)據(jù)控制視圖的原理解析
這篇主要講的就是vue很重要的一塊知識點(diǎn),雙向數(shù)據(jù)綁定是如何實(shí)現(xiàn)的。一開始看這一塊的內(nèi)容的時(shí)候比較迷茫,迷茫在以下幾個(gè)點(diǎn):
- 這塊內(nèi)容該從哪邊入手
- 數(shù)據(jù)變化是如何驅(qū)動視圖層更新的
- 做題深化知識點(diǎn)
從哪邊著手去看響應(yīng)式原理
我這邊提供三個(gè)方向,從這三個(gè)方向,你都可以看到watcher的使用,然后watcher的使用過程中,會摻雜到observer以及dep,然后以點(diǎn)帶面,對整體進(jìn)行梳理
初始化的render流程去看
在lifecycle這個(gè)文件中的mountComponent這個(gè)方法里,創(chuàng)建了一個(gè)watcher。代碼如下:
new Watcher(vm, updateComponent, noop, {
before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate')
}
}
}, true /* isRenderWatcher */)
可以透過這個(gè)傳參,梳理出整一個(gè)
- 從watch的角度去看
- 從computed的角度去看
數(shù)據(jù)變化是如何驅(qū)動視圖層更新的
這個(gè)問題其實(shí)可以分兩個(gè)方面去看:
如何知道數(shù)據(jù)變化了
如何知道某一塊視圖和數(shù)據(jù)有關(guān),并更新他 如何知道數(shù)據(jù)變化了
答案:數(shù)據(jù)劫持
數(shù)據(jù)劫持的兩種方式
Object.defineProperty proxy
Vue3.0中的數(shù)據(jù)劫持是用proxy來實(shí)現(xiàn)的,目前閱讀的源碼中,都是以 Object.defineProperty 這種方式來實(shí)現(xiàn)的。
如何知道某一塊視圖和數(shù)據(jù)有關(guān),并更新他
答案:依賴收集以及訂閱更新
詳細(xì)解讀過程:用圖告訴你響應(yīng)式原理
這里僅用一個(gè)簡單的例子和圖,來明確一下整個(gè)流程
<div id="app">
{{ message }}
{{ message1 }}
<input type="text" v-model="message">
<div @click="changeMessage">改變message</div>
</div>
var app = new Vue({
el: '#app',
data: {
message: '1',
message1: '2',
},
methods: {
changeMessage() {
this.message = '2'
}
},
watch: {
message: function(val) {
this.message1 = val
}
}
})
依賴收集流程圖

依賴收集的最終結(jié)果:

訂閱更新流程圖:

。
做題深化知識點(diǎn)
題目如下:
1、簡述Vue的響應(yīng)式原理
2、計(jì)算屬性和watch的區(qū)別
3、Vue中給data中的對象屬性添加一個(gè)新的屬性時(shí)會發(fā)生什么,如何解決?
對于第一和第二在這里就不花篇幅去說明。
Vue中給data中的對象屬性添加一個(gè)新的屬性時(shí)會發(fā)生什么,如何解決?
我們在做業(yè)務(wù)的時(shí)候經(jīng)常會遇到這樣的情況,我舉一個(gè)簡單的例子:
<template>
<div>
<ul>
<li v-for="value in obj" :key="value">
{{value}}
</li>
</ul>
<button @click="addObjB">添加obj.b</button>
</div>
</template>
<script>
export default {
data () {
return {
obj: {
a: 'obj.a'
}
}
},
methods: {
addObjB () {
this.obj.b = 'obj.b'
console.log(this.obj)
}
}
}
</script>
<style></style>
依賴收集流程:

從中我們可以發(fā)現(xiàn),renderWatch是有收集 Dep(obj) 和 Dep(Obj.a) 的,但是當(dāng)我們改變Obj的時(shí)候,并沒有觸發(fā)視圖的更新。因?yàn)槲覀冊诟淖僶bj的值的時(shí)候,并沒有去觸發(fā)Dep(obj)。
產(chǎn)生問題的本質(zhì)原因:
1、vue會在state.js文件的initData的方法中,將data屬性中的每一個(gè)key都變成響應(yīng)式屬性。
2、視圖在渲染過程中,會將renderWatcher收集到用到的值的dep中,方便依賴更新(不懂的在回過去看一下依賴收集流程)
3、當(dāng)你額外添加一個(gè)屬性的時(shí)候,該屬性并不是響應(yīng)式屬性。
那如何去改變:
addObjB () {
// this.obj.b = 'obj.b'
this.$set(this.obj, 'b', 'obj.b')
console.log(this.obj)
}
總結(jié)
這篇文章是年度總結(jié)的開篇,后續(xù)會繼續(xù)總結(jié)初始化部分、render部分和patch部分。希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Element el-table的formatter和scope?template不能同時(shí)存在問題解決辦法
本文主要介紹了ElementUI?el-table?的?formatter?和?scope?template?不能同時(shí)存在問題解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
從零擼一個(gè)pc端vue的ui組件庫( 計(jì)數(shù)器組件 )
這篇文章主要介紹了pc端vue的ui組件庫的實(shí)現(xiàn)方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
ElementUI的this.$notify.close()調(diào)用不起作用的解決
本文主要介紹了ElementUI的this.$notify.close()調(diào)用不起作用的解決,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
vue打包相關(guān)細(xì)節(jié)整理(小結(jié))
這篇文章主要介紹了vue打包相關(guān)細(xì)節(jié)整理(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
vue項(xiàng)目打包發(fā)布后接口報(bào)405錯(cuò)誤的解決
這篇文章主要介紹了vue項(xiàng)目打包發(fā)布后接口報(bào)405錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Vue.js實(shí)現(xiàn)文件上傳和進(jìn)度條顯示功能
在現(xiàn)代Web開發(fā)中,文件上傳是一個(gè)常見而重要的需求,無論是在用戶上傳頭像、文檔或者其他類型的文件時(shí),良好的用戶體驗(yàn)都是至關(guān)重要的,在這篇博客中,我們將介紹如何使用Vue.js來實(shí)現(xiàn)文件上傳功能,同時(shí)顯示上傳進(jìn)度條,需要的朋友可以參考下2024-11-11

