Vue雙向數(shù)據(jù)綁定與響應式原理深入探究
一、雙向數(shù)據(jù)綁定和數(shù)據(jù)響應式是相同的嗎
不相同,原因如下:
響應式是指通過數(shù)據(jù)區(qū)驅動DOM視圖的變化,是單向的過程。
雙向數(shù)據(jù)綁定就是無論用戶更新View還是Model,另一個都能跟著自動更新。
- 例如:當用戶填寫表單時,View的狀態(tài)就被更新了,如果此時可以自動更新Model的狀態(tài),那就相當于我們把Model和View做了雙向綁定。
- 雙向數(shù)據(jù)綁定的數(shù)據(jù)和DOM是一個雙向的關系。
- 響應式是雙向綁定的一環(huán)。
二、雙向數(shù)據(jù)綁定的原理
雙向綁定由三個重要部分(MVVM)構成:
- 數(shù)據(jù)層(Model):應用的數(shù)據(jù)及業(yè)務邏輯;
- 視圖層(View):應用的展示效果,各類UI組件;
- 業(yè)務邏輯層(ViewModel):框架封裝的核心,它負責將數(shù)據(jù)與視圖關聯(lián)起來。
ViewModel的主要職責是:數(shù)據(jù)變化后更新視圖;視圖變化后更新數(shù)據(jù)。
ViewModel有兩個主要組成部分:
- 監(jiān)聽器(Observer):對所有數(shù)據(jù)的屬性進行監(jiān)聽;
- 解析器(Compiler):對每個元素節(jié)點的指令進行掃描跟解析,根據(jù)指令模板替換數(shù)據(jù),以及綁定響應的更新函數(shù)。
Vue中體現(xiàn)出的雙向綁定有兩種方式:v-model屬性和.sync修飾符
v-model屬性:v-model也有兩種使用場景,一是作用在表單元素上,二是作用在組件上
(1)作用在表單元素上:動態(tài)綁定了input的value指向了變量,并且在觸發(fā)input事件的時候動態(tài)的把變量設置為目標值:
<input type="text" v-model="message"> //相當于 <input type="text" v-bind:value="message" v-on:input="message=$event.target.value">
(2)作用在組件上:在自定義組件中,v-model 默認會利用名為 value 的 prop和名為 input 的事件。通過子組件中的 $emit 方法派發(fā) input 事件,父組件監(jiān)聽 input 事件中傳遞的 value 值,并存儲在父組件 data 中;然后父組件再通過 prop 的形式傳遞給子組件 value 值,再子組件中綁定 input 的 value 屬性即可。
<child :value="message" @input="function(e){message = e}"></child>
.sync修飾符:父組件向子組件傳遞數(shù)據(jù)的方式有很多種,props是其中的一種,但是它只能單向傳遞,使用.sync可以實現(xiàn)子組件修改父組件的數(shù)據(jù)。
<!-- 父組件給子組件傳入一個setNum函數(shù) --> <child :num.sync="numParent"> <script> //子組件通過調用這個函數(shù)來實現(xiàn)修改父組件的狀態(tài) methods: { changNum(){ this.$emit('update:num',666) } </script>
三、數(shù)據(jù)響應式的原理與實現(xiàn)
流程:
- new Vue()首先執(zhí)行初始化,對data執(zhí)行響應化處理,這個過程發(fā)生Observe中;
- 同時對模板執(zhí)行編譯,找到其中動態(tài)綁定的數(shù)據(jù),從data中獲取并初始化視圖,這個過程發(fā)生在Complie中;
- 同時定義一個更新函數(shù)和Watcher,將來對應數(shù)據(jù)變化時Watcher會調用更新函數(shù);
- 由于data的某個key在一個視圖中可能出現(xiàn)多次,所以每個key都需要一個管家Dep來管理多個Watcher;
- 將來data中數(shù)據(jù)一旦發(fā)生變化,會首先找到對應的Dep,通知所有Watcher執(zhí)行更新函數(shù)。
主要解決兩個問題
1. app.message修改數(shù)據(jù),Vue內部是如何監(jiān)聽message數(shù)據(jù)的改變的;
——Object.defineProperty ->監(jiān)聽對象屬性的改變
2. 當數(shù)據(jù)發(fā)送改變,Vue是如何知道要通知哪些人,界面發(fā)生刷新
——發(fā)布訂閱者模式
實現(xiàn):
原代碼:
<body> <div id="app"> {{message}} {{message}} {{message}} {{name}} </div> </body> <script> const app = new Vue({ el:'#app', data:{ message:'哈哈哈', name:'fanafan' } }) </script>
問題1:app.message修改數(shù)據(jù),Vue內部是如何監(jiān)聽message數(shù)據(jù)的改變的
const obj = { message:'哈哈哈', name:'fanafan' } Object.keys(obj).forEach(key => { let value = obj[key] Object.defineProperty(obj,key,{ set(newValue){ console.log("監(jiān)聽" + key +"的改變"); value = newValue }, get(){ console.log("獲取" + key + "對應的值"); return value } }) })
問題2:當數(shù)據(jù)發(fā)送改變,Vue是如何知道要通知哪些人,界面發(fā)生刷新
// 發(fā)布者訂閱者 class Dep{ constructor(){ this.subs = [] } addSub(watcher){ this.subs.push(watcher) } notify(){ this.subs.forEach(item=>{ item.update() }) } } class Watcher { constructor(name){ this.name = name; } update(){ console.log(this.name + '發(fā)生update'); } } const dep = new Dep() const w1 = new Watcher('張三') dep.addSub(w1) const w2 = new Watcher('李四') dep.addSub(w2) const w3 = new Watcher('王五') dep.addSub(w3) dep.notify()
到此這篇關于Vue雙向數(shù)據(jù)綁定與響應式原理深入探究的文章就介紹到這了,更多相關Vue雙向數(shù)據(jù)綁定內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決vue-cli創(chuàng)建項目的loader問題
下面小編就為大家分享一篇解決vue-cli創(chuàng)建項目的loader問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看看吧2018-03-03