深入了解Vue中雙向數(shù)據(jù)綁定原理
數(shù)據(jù)的變化反應到視圖
前面我們了解到數(shù)據(jù)劫持之后,我們可以在數(shù)據(jù)發(fā)生修改之后做任何我們想要做的事情,操作視圖當然也是OK的
命令式操作視圖
目標:我們通過原始的操作dom的方式讓每一次的name的最新值都能顯示到p元素內(nèi)部
<div id="app"> <p></p> </div> <script> let data = { name: '小蘭同學', 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進行更新 document.querySelector('#app p').innerHTML = data.name } }) } // 首次渲染 document.querySelector('#app p').innerHTML = data.name </script>
聲明式操作視圖
目標:我們將data中name屬性的值作為文本渲染到標記了v-text的p標簽內(nèi)部,在vue中,我們把這種標記式的聲明式渲染叫做指令
<div id="app"> <p v-text="name"></p> </div> <script> let data = { name: '小蘭同學', 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進行更新 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>
小結
不管是指令也好,插值表達式也好,這些都是將數(shù)據(jù)反應到視圖的標記而已,通過標記我們可以把數(shù)據(jù)的變化響應式的反應到對應的dom位置上去
找標記,把數(shù)據(jù)綁定到dom的過程,我們稱之為binding
視圖的變化反應到數(shù)據(jù)
目標:將data中的message屬性對應的值渲染到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: '小蘭同學', 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進行更新 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] // 視圖變化反應到數(shù)據(jù) 無非是事件監(jiān)聽反向修改 node.addEventListener('input', (e) => { data[dataProp] = e.target.value }) } }) } }) } // 首次渲染 compile() </script>
現(xiàn)存的問題
無法做到精準更新
<div id="app"> <p v-text="name"></p> <p v-text="age"></p> <p v-text="name"></p> </div> <script> let data = { name: '小蘭同學', 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進行更新 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ù)綁定原理的詳細內(nèi)容,更多關于Vue雙向數(shù)據(jù)綁定的資料請關注腳本之家其它相關文章!
相關文章
vue+ElementUI 關閉對話框清空驗證,清除form表單的操作
這篇文章主要介紹了vue+ElementUI 關閉對話框清空驗證,清除form表單的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08Vue選項之propsData傳遞數(shù)據(jù)方式
這篇文章主要介紹了Vue選項之propsData傳遞數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10VUE使用docxtemplater導出word文檔實例(帶圖片)
docxtemplate支持的功能很多,語法包含變量替換、條件判斷、循環(huán)、列表循環(huán)、表格循環(huán)等,下面這篇文章主要給大家介紹了關于VUE使用docxtemplater導出word功能(帶圖片)的相關資料,需要的朋友可以參考下2023-06-06解決vue.js 數(shù)據(jù)渲染成功仍報錯的問題
今天小編就為大家分享一篇解決vue.js 數(shù)據(jù)渲染成功仍報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08