歡迎各位小伙伴們!
為大家推薦一款刷題神奇哦 點擊鏈接訪問牛客網
各大互聯網大廠面試真題。從基礎到入階乃至原理刨析類面試題 應有盡有,趕快來裝備自己吧!助你面試穩操勝券,solo全場面試官
文章目錄
- 數據的變化反應到視圖
- 命令式操作視圖
- 聲明式操作視圖
- 小結
- 視圖的變化反應到數據
- 現存的問題
- 寫在最后
數據的變化反應到視圖
前面我們了解到數據劫持之后,我們可以在數據發生修改之后做任何我們想要做的事情,操作視圖當然也是OK的
命令式操作視圖
目標:我們通過原始的操作dom的方式讓每一次的name的最新值都能顯示到p元素內部
<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 // 數據發生變化,操作dom進行更新document.querySelector('#app p').innerHTML = data.name}})}// 首次渲染document.querySelector('#app p').innerHTML = data.name
</script>
聲明式操作視圖
目標:我們將data中name屬性的值作為文本渲染到標記了v-text的p標簽內部,在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// 數據發生變化,操作dom進行更新compile()}})}// function compile() {let app = document.getElementById('app')// 1.拿到app下所有的子元素const nodes = app.childNodes // [text, input, text]//2.遍歷所有的子元素nodes.forEach(node => {// nodeType為1為元素節點if (node.nodeType === 1) {const attrs = node.attributes// 遍歷所有的attrubites找到 v-modelArray.from(attrs).forEach(attr => {const dirName = attr.nodeNameconst dataProp = attr.nodeValueif (dirName === 'v-text') {node.innerText = data[dataProp]}})}})}// 首次渲染compile()
</script>
小結
- 不管是指令也好,插值表達式也好,這些都是將數據反應到視圖的標記而已,通過標記我們可以把數據的變化響應式的反應到對應的dom位置上去
- 找標記,把數據綁定到dom的過程,我們稱之為
binding
視圖的變化反應到數據
目標:將data中的message屬性對應的值渲染到input上面,同時input值發生修改之后,可以反向修改message的值,在vue系統中,v-model指令就是干這個事情的,下面我們就實現一下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) {// 數據發生變化,操作dom進行更新if (newVal === value) {return}value = newValcompile()}})}// 編譯函數function compile() {let app = document.getElementById('app')// 1.拿到app下所有的子元素const nodes = app.childNodes // [text, input, text]//2.遍歷所有的子元素nodes.forEach(node => {// nodeType為1為元素節點if (node.nodeType === 1) {const attrs = node.attributes// 遍歷所有的attrubites找到 v-modelArray.from(attrs).forEach(attr => {const dirName = attr.nodeNameconst dataProp = attr.nodeValueif (dirName === 'v-model') {node.value = data[dataProp]// 視圖變化反應到數據 無非是事件監聽反向修改node.addEventListener('input', (e) => {data[dataProp] = e.target.value})}})}})}// 首次渲染compile()
</script>
現存的問題
無法做到精準更新
<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) {// 數據發生變化,操作dom進行更新if (newVal === value) {return}value = newValcompile()}})}// 編譯函數function compile() {let app = document.getElementById('app')// 1.拿到app下所有的子元素const nodes = app.childNodes // [text, input, text]//2.遍歷所有的子元素nodes.forEach(node => {// nodeType為1為元素節點if (node.nodeType === 1) {const attrs = node.attributesArray.from(attrs).forEach(attr => {const dirName = attr.nodeNameconst dataProp = attr.nodeValueconsole.log( dirName,dataProp)if (dirName === 'v-text') {console.log(`更新了${dirName}指令,需要更新的屬性為${dataProp}`)node.innerText = data[dataProp]}})}})}// 首次渲染compile()
</script>
下節中對本問題進行修復
寫在最后
?原創不易,還希望各位大佬支持一下\textcolor{blue}{原創不易,還希望各位大佬支持一下}原創不易,還希望各位大佬支持一下
👍 點贊,你的認可是我創作的動力!\textcolor{green}{點贊,你的認可是我創作的動力!}點贊,你的認可是我創作的動力!
?? 收藏,你的青睞是我努力的方向!\textcolor{green}{收藏,你的青睞是我努力的方向!}收藏,你的青睞是我努力的方向!
?? 評論,你的意見是我進步的財富!\textcolor{green}{評論,你的意見是我進步的財富!}評論,你的意見是我進步的財富!