深入了解Vue中雙向數(shù)據(jù)綁定原理
數(shù)據(jù)的變化反應(yīng)到視圖
前面我們了解到數(shù)據(jù)劫持之后,我們可以在數(shù)據(jù)發(fā)生修改之后做任何我們想要做的事情,操作視圖當(dāng)然也是OK的
命令式操作視圖
目標(biāo):我們通過原始的操作dom的方式讓每一次的name的最新值都能顯示到p元素內(nèi)部
<div id="app">
<p></p>
</div>
<script>
let data = {
name: '小蘭同學(xué)',
age: 18,
height:180
}
// 遍歷每一個屬性
Object.keys(data).forEach((key)=>{
// key 屬性名
// data[key] 屬性值
defineReactive(data,key,data[key])
})
function defineReactive(data,key,value){
Object.defineProperty(data,key,{
get(){
return value
},
set(newVal){
value = newVal
// 數(shù)據(jù)發(fā)生變化,操作dom進(jìn)行更新
document.querySelector('#app p').innerHTML = data.name
}
})
}
// 首次渲染
document.querySelector('#app p').innerHTML = data.name
</script>
聲明式操作視圖
目標(biāo):我們將data中name屬性的值作為文本渲染到標(biāo)記了v-text的p標(biāo)簽內(nèi)部,在vue中,我們把這種標(biāo)記式的聲明式渲染叫做指令
<div id="app">
<p v-text="name"></p>
</div>
<script>
let data = {
name: '小蘭同學(xué)',
age: 18,
height: 180
}
// 遍歷每一個屬性
Object.keys(data).forEach((key) => {
// key 屬性名
// data[key] 屬性值
// data 原對象
defineReactive(data, key, data[key])
})
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
return value
},
set(newVal) {
value = newVal
// 數(shù)據(jù)發(fā)生變化,操作dom進(jìn)行更新
compile()
}
})
}
//
function compile() {
let app = document.getElementById('app')
// 1.拿到app下所有的子元素
const nodes = app.childNodes // [text, input, text]
//2.遍歷所有的子元素
nodes.forEach(node => {
// nodeType為1為元素節(jié)點
if (node.nodeType === 1) {
const attrs = node.attributes
// 遍歷所有的attrubites找到 v-model
Array.from(attrs).forEach(attr => {
const dirName = attr.nodeName
const dataProp = attr.nodeValue
if (dirName === 'v-text') {
node.innerText = data[dataProp]
}
})
}
})
}
// 首次渲染
compile()
</script>
小結(jié)
不管是指令也好,插值表達(dá)式也好,這些都是將數(shù)據(jù)反應(yīng)到視圖的標(biāo)記而已,通過標(biāo)記我們可以把數(shù)據(jù)的變化響應(yīng)式的反應(yīng)到對應(yīng)的dom位置上去
找標(biāo)記,把數(shù)據(jù)綁定到dom的過程,我們稱之為binding
視圖的變化反應(yīng)到數(shù)據(jù)
目標(biāo):將data中的message屬性對應(yīng)的值渲染到input上面,同時input值發(fā)生修改之后,可以反向修改message的值,在vue系統(tǒng)中,v-model指令就是干這個事情的,下面我們就實現(xiàn)一下v-model的功能
<div id="app">
<input v-model="name" />
</div>
<script>
let data = {
name: '小蘭同學(xué)',
age: 18,
height: 170
}
// 遍歷每一個屬性
Object.keys(data).forEach((key) => {
// key 屬性名
// data[key] 屬性值
// data 原對象
defineReactive(data, key, data[key])
})
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
return value
},
set(newVal) {
// 數(shù)據(jù)發(fā)生變化,操作dom進(jìn)行更新
if (newVal === value) {
return
}
value = newVal
compile()
}
})
}
// 編譯函數(shù)
function compile() {
let app = document.getElementById('app')
// 1.拿到app下所有的子元素
const nodes = app.childNodes // [text, input, text]
//2.遍歷所有的子元素
nodes.forEach(node => {
// nodeType為1為元素節(jié)點
if (node.nodeType === 1) {
const attrs = node.attributes
// 遍歷所有的attrubites找到 v-model
Array.from(attrs).forEach(attr => {
const dirName = attr.nodeName
const dataProp = attr.nodeValue
if (dirName === 'v-model') {
node.value = data[dataProp]
// 視圖變化反應(yīng)到數(shù)據(jù) 無非是事件監(jiān)聽反向修改
node.addEventListener('input', (e) => {
data[dataProp] = e.target.value
})
}
})
}
})
}
// 首次渲染
compile()
</script>
現(xiàn)存的問題
無法做到精準(zhǔn)更新
<div id="app">
<p v-text="name"></p>
<p v-text="age"></p>
<p v-text="name"></p>
</div>
<script>
let data = {
name: '小蘭同學(xué)',
age: 18,
height: 180
}
// 遍歷每一個屬性
Object.keys(data).forEach((key) => {
// key 屬性名
// data[key] 屬性值
// data 原對象
defineReactive(data, key, data[key])
})
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
return value
},
set(newVal) {
// 數(shù)據(jù)發(fā)生變化,操作dom進(jìn)行更新
if (newVal === value) {
return
}
value = newVal
compile()
}
})
}
// 編譯函數(shù)
function compile() {
let app = document.getElementById('app')
// 1.拿到app下所有的子元素
const nodes = app.childNodes // [text, input, text]
//2.遍歷所有的子元素
nodes.forEach(node => {
// nodeType為1為元素節(jié)點
if (node.nodeType === 1) {
const attrs = node.attributes
Array.from(attrs).forEach(attr => {
const dirName = attr.nodeName
const dataProp = attr.nodeValue
console.log( dirName,dataProp)
if (dirName === 'v-text') {
console.log(`更新了${dirName}指令,需要更新的屬性為${dataProp}`)
node.innerText = data[dataProp]
}
})
}
})
}
// 首次渲染
compile()
</script>
以上就是深入了解Vue中雙向數(shù)據(jù)綁定原理的詳細(xì)內(nèi)容,更多關(guān)于Vue雙向數(shù)據(jù)綁定的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue+ElementUI 關(guān)閉對話框清空驗證,清除form表單的操作
這篇文章主要介紹了vue+ElementUI 關(guān)閉對話框清空驗證,清除form表單的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
vue2.0/3.0的響應(yīng)式原理及區(qū)別淺析
這篇文章主要給大家介紹了關(guān)于vue2.0/3.0響應(yīng)式原理及區(qū)別的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
Vue 中如何利用 new Date() 獲取當(dāng)前時間
在 Vue 開發(fā)中,利用 new Date() 方法可以方便地獲取當(dāng)前時間,并通過 Date 對象的方法進(jìn)行時間格式化和操作。通過本文的介紹,您應(yīng)該對在 Vue 中獲取當(dāng)前時間有了更深入的了解,并了解了一些常見的時間操作方法,需要的朋友可以參考下2023-07-07
Vue選項之propsData傳遞數(shù)據(jù)方式
這篇文章主要介紹了Vue選項之propsData傳遞數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
VUE使用docxtemplater導(dǎo)出word文檔實例(帶圖片)
docxtemplate支持的功能很多,語法包含變量替換、條件判斷、循環(huán)、列表循環(huán)、表格循環(huán)等,下面這篇文章主要給大家介紹了關(guān)于VUE使用docxtemplater導(dǎo)出word功能(帶圖片)的相關(guān)資料,需要的朋友可以參考下2023-06-06
解決vue.js 數(shù)據(jù)渲染成功仍報錯的問題
今天小編就為大家分享一篇解決vue.js 數(shù)據(jù)渲染成功仍報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08

