摘要:執(zhí)行的時候,會綁定上下文對象為組件實例于是中的就能取到組件實例本身,的代碼塊頂層作用域就綁定為了組件實例于是內(nèi)部變量的訪問,就會首先訪問到組件實例上。其中的獲取,就會先從組件實例上獲取,相當(dāng)于。
寫文章不容易,點個贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】
如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧
【Vue原理】VModel - 白話版
說到 Vue,感覺第一印象就是雙向綁定,所以v-model鍵值是Vue印象的半壁江山啊,這么重要的東西,你好歹要知道是怎么實現(xiàn)的吧
我們今天就來講解雙向綁定的工作原理,你應(yīng)該知道,雙向綁定就是通過綁定 dom 事件來實現(xiàn)的,可是,怎么綁定的事件,綁定什么事件?
首先,雙向綁定,我個人認(rèn)為應(yīng)該分為 初始化綁定 和 雙向更新 兩part。
初始化綁定,就是初始化時給表單元素綁定值,綁定事件,為雙向更新做準(zhǔn)備
雙向更新,就是任意一邊變化,同時能讓另一個邊更新
雙向更新那是后話,只有一開始時成功執(zhí)行綁定操作才會有之后 雙向更新這個東西,所以,今天按順序來了解兩個part,從四個問題開始
1、v-model 怎么給表單綁定數(shù)據(jù)
2、v-model 綁定什么事件
3、v-model 怎么綁定事件
4、v-model 如何進行雙向更新
TIP
v-model 還可以用在 自定義組件上,但是很明顯,這次我們先不講這一塊,而是先將正常的表單使用
先看結(jié)論我們先以 input text 類型講解,對于其他的表單元素,流程都差不多,只是中間涉及的內(nèi)容不同。所以就先講個例子,然后具體在源碼版全部一起說
1、怎么賦值?v-model 綁定的數(shù)據(jù)賦值給表單元素的 value 屬性
2、怎么綁定事件?解析不同表單元素,配置相應(yīng)的事件名和事件回調(diào),在插入dom之前,addEventListener 綁定上事件
3、怎么雙綁?外部變化,觸發(fā)事件回調(diào),event.target.value 賦值給model綁定的數(shù)據(jù);內(nèi)部變化,修改表單元素屬性 value
看完結(jié)論,有點懵?我們來看看具體的內(nèi)容,結(jié)果導(dǎo)向來進行學(xué)習(xí)
下面的講解以下面這個為例
v-model 怎么給表單綁定數(shù)據(jù)獲取值流程
首先,上面例子解析后的渲染函數(shù)是下面這樣(已簡化,只保留表單值相關(guān))
(function(){ with(this){ return _c("div",[ _c("input", domProps:{"value":name} ) ]) } })
1、這個渲染函數(shù)是沒有執(zhí)行的 匿名函數(shù)。執(zhí)行的時候,會綁定上下文對象為 組件實例
2、于是 with(this) 中的 this 就能取到 組件實例本身,with 的代碼塊 頂層作用域 就綁定為了 組件實例
3、于是 with 內(nèi)部變量的訪問,就會首先訪問到 組件實例上。其中 name 的 獲取,就會先從 組件實例上獲取,相當(dāng)于 vm.name。賦值完成后,domProps 就是下面這樣
{ domProps:{value:111} }
4、上面的 value 是 v-model 解析成的原生屬性,保存在屬于該節(jié)點 input 的 domProps 對象存儲器中
綁定值流程
創(chuàng)建dom input 之后,插入dom input 之前,遍歷該 input 的 domProps ,逐個添加給 input dom
簡化后的代碼像下面這樣進行賦值
for(var i in domProps){ input[i]=domProps[i] }
其中給節(jié)點賦值就是這樣
input.value = 111v-model 綁定什么事件
不同的表單元素使用v-model,會綁定不同的 事件
change 事件
select,checkbox,radio
input 事件
這是默認(rèn)事件,當(dāng)不是上面三種表單元素時,會解析成 input 事件
比如 text、number 等 input 元素和 textarea
TIP
實際上關(guān)于 input 和 textarea 綁定的事件遠(yuǎn)不止 input 一個事件,但是涉及內(nèi)容太多,打算放在源碼版說明,這里先簡單默認(rèn)是 input 事件
v-model 怎么綁定事件上面例子解析成下面的渲染函數(shù)(已簡化,只保留事件相關(guān))
with(this) { return _c("div", [ _c("input", { on: { "input": function($event) { name = $event.target.value } } } )]) }
解析事件流程
1解析不同表單元素,配置不同的事件
2拼裝 事件回調(diào)函數(shù),不同表單元素,回調(diào)不一樣
3把 事件名和拼裝回調(diào) 配套 保存給相應(yīng)的表單元素的 on 事件存儲器
什么時候綁定事件
生成 input dom 之后,插入input dom 之前
怎么綁
使用之前保存的 事件名和 事件回調(diào),給 input dom 像下面這樣綁定上事件
input.addEventListener("input",function($event) { name = $event.target.value })v-model 如何進行雙向更新
雙向,指的是 外部和內(nèi)部
外部變化:用戶手動改變表單值,輸入或者選擇
內(nèi)部變化:從內(nèi)部修改綁定值
內(nèi)部變化
1、v-model 綁定了 name ,name 會收集到 本組件的 watcher
a. 下面渲染函數(shù)執(zhí)行時,會綁定本身組件實例為上下文對象
b. name 訪問的是 組件實例的 name
c. name 此時便收集到了 當(dāng)前正在渲染的組件實例,當(dāng)前渲染的實例是自己,于是收集到了自身的 watcher
(function(){ with(this){ return _c("div",[_c("input", domProps:{"value":(name)}) ]) } })
如果你不懂 收集 watcher 什么意思,建議看下我的另一篇文章
【Vue原理】響應(yīng)式原理 - 白話版
2、內(nèi)部修改 name 變化,通知收集器內(nèi)的 watcher 更新,所以本組件會更新,上面的渲染函數(shù)重新執(zhí)行,便 重新從實例讀取 name
3、重新給 input dom 的 value 賦值,于是 頁面就更新了
怎么賦值?那是回到第一個問題了,兄弟
外部變化
手動改變表單,事件觸發(fā),執(zhí)行事件回調(diào)(下面這個),更新組件數(shù)據(jù) name
function($event) { name = $event.target.value }
更新內(nèi)部數(shù)據(jù)流程
1、當(dāng)事件觸發(fā)的時候,會把 表單的值 賦值給 name
2、name 是從 組件實例上訪問的
3、所以這次賦值會 直接改變組件實例的 name
回調(diào)怎么賦值給組件實例的name
一開始不懂,所以不理解,也沒查到,寫了個例子,大概理解了意思
1、因為事件回調(diào) 在 with 里面聲明
2、于是事件回調(diào)的 作用域鏈最頂層 就加上了一層 with 綁定的作用域
3、就算事件回調(diào)不在 with 中執(zhí)行,事件回調(diào)中的 變量訪問,也會先訪問之前 with 綁定過的作用域,因為作用域鏈的最頂層
with舉栗子
var name=22 var a={name:"a"} with(a){ var fn=function(){ console.log(name) } } fn()
你認(rèn)為 fn 執(zhí)行的時候,會打印出什么呢?行了,給你看結(jié)果了
好吧,再一次深刻認(rèn)識到一個知識點,with 綁定作用域原來這么強,離開with執(zhí)行,還是先訪問他的作用域,脫離不出魔爪啊,強盜作用域
回來總結(jié)!
于是當(dāng)事件回調(diào)執(zhí)行的時候,會 直接賦值 給 組件實例的name,這樣便通過外部改變了內(nèi)部數(shù)據(jù)
TIP
外部變化,本來可能會存在一種情況
a、手動修改表單后, 回調(diào)內(nèi)會更新組件的值
b、組件的值更新之后,會通知組件更新,組件更新時,便又會重新把input 賦值一遍
非常多余的一步操作,所以這里,Vue做一個判斷,判斷舊值和 新值是否相等,不等才更新,關(guān)于舊值,會保存在 dom 的 _value 屬性
總結(jié)v-model 三要素
1、綁定屬性
2、綁定事件
3、屬性+事件組合完成雙向更新
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105204.html
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關(guān)注公眾號也可以吧原理源碼版之詳解今天我們來看看處 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 ...
摘要:因為失去焦點之后被強制更新了一波嗯,這就是的作用,把頁面上的顯示值也過濾一遍 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】VModel - 源碼版之input詳...
摘要:首先,兄弟,容我先說幾句涉及源碼很多,篇幅很長,我都已經(jīng)分了上下三篇了,依然這么長,但是其實內(nèi)容都差不多一樣,但是我還是毫無保留地給你了。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關(guān)注公眾號也可以吧原理源碼版之節(jié)點數(shù)據(jù)拼接上一篇我們 寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究...
摘要:所以我今后打算把每一個內(nèi)容分成白話版和源碼版。有什么錯誤的地方,感謝大家能夠指出響應(yīng)式系統(tǒng)我們都知道,只要在實例中聲明過的數(shù)據(jù),那么這個數(shù)據(jù)就是響應(yīng)式的。什么是響應(yīng)式,也即是說,數(shù)據(jù)發(fā)生改變的時候,視圖會重新渲染,匹配更新為最新的值。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 V...
閱讀 3255·2021-11-11 16:55
閱讀 2567·2021-10-13 09:39
閱讀 2467·2021-09-13 10:27
閱讀 2181·2019-08-30 15:55
閱讀 3106·2019-08-30 15:54
閱讀 3154·2019-08-29 16:34
閱讀 1848·2019-08-29 12:41
閱讀 1087·2019-08-29 11:33