摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之詳解今天我們來看看處
寫文章不容易,點個贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧
研究基于 Vue版本 【2.5.17】
如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧
【Vue原理】VModel - 源碼版 之 select 詳解
今天我們來看看 v-model 處理 select 有什么特殊的地方
前面已經有三篇說明VModel了
【Vue原理】VModel - 白話版
【Vue原理】VModel - 源碼版 之 表單元素綁定流程
【Vue原理】VModel - 源碼版之input詳解
通過第一篇源碼分享,我們就知道 Vue是通過 設置 select 的 selectedIndex 來控制選項的,
哈哈,現在我們就是來分析到底是怎么設置 selectedIndex 的
好的,我們一定要帶著問題進行學習,這樣學完才有用
1、Vue 如何設置 selectedIndex 2、Vue 在哪里設置 selectedIndexVue 如何設置 selectedIndex
Vue 是通過 一個 setSelected 的方法專門來設置 selectedIndex 的,我們來看下源碼
function setSelected(el, binding, vm) { var selected, option; for (var i = 0, l = el.options.length; i < l; i++) { option = el.options[i]; if (isMultiple) { selected = value.indexOf(option) > -1; if (option.selected !== selected) { option.selected = selected; } } else { if (option.value == value) { if (el.selectedIndex !== i) { el.selectedIndex = i; } return } } } if (!isMultiple) { el.selectedIndex = -1; } }
兩處會修改 selectedIndex 的地方我已經加紅加粗
簡單解釋下 setSelected 的作用
1、綁定值無法匹配任何option 時,設置 selectedIndex =-1,然后select 就會顯示空
舉栗子
select 的 selectedIndex 是-1,然后選擇框內顯示空
2、選擇時,如果多個options 值相等時,只取第一個相等項
舉栗子
三個選項的 value 都一樣
哈哈,我明明選了3,但是 顯示1,這就是 Vue 做的處理,多個相同值的選擇,只去第一個
但是這個也是有條件的,必須在 value 變化的時候,才會進行更新,于是才會有 判斷操作
比如現在select 的value是 1,你再選擇一個 也是 1 的其他選項,Vue 就不會更新,也就不會判斷,你選了就選了,不管你了
看圖,初始化 select value 為空,然后選擇 value 是1 的 第三個選項,
哦豁,突然變成第一個選項了
而我再選擇 3 和 2 的時候,卻不會變成 第一個選項,因此 3 和2 的 value 都是 1,value 沒有變化,select 不會更新
3、選擇后,options 變化,會根據之前的選擇,更新它在options的位置
options 改變了,然后把 1 的位置變成最后一個,然后 Vue 就會相應地把 selectedIndex 的位置更新為 新options 中對應的位置
在哪里設置 selectedIndexVue 會在 v-model 的兩個鉤子函數中更新 select 的 selectedIndex
inserted
當dom被插入到頁面中后,會觸發這個鉤子函數
上一篇詳解input我們已經能知道,inserted 會處理select
看下 inserted 源碼(只有select 處理部分)
function inserted(el, binding, vnode, oldVnode) { if (vnode.tag === "select") { // 設置 select 的selectedIndex 初始值 setSelected(el, binding, vnode.context); // 把options 的value,全都保存到一個數組 el._vOptions = [].map .call(el.options, function(o){ return o.value }); } }
componentUpdated
當組件更新完畢之后,觸發 這個鉤子
這個鉤子函數只針對 select 處理
上 componentUpdated 鉤子函數源碼
function componentUpdated(el, binding, vnode) { if (vnode.tag === "select") { setSelected(el, binding, vnode.context); // 這是之前保存的 舊 的 options 的 所有 value 的數組 比如[ 1,2,3] var prevOptions = el._vOptions; // 拿到 現在所有 option 的value 存到數組 var curOptions = el._vOptions = [].map.call(el.options, getValue); // 當 options 變化,而且跟舊option 每個都不一樣 if (curOptions.some(function(o, i) { return ! (o==prevOptions[i]) })) { var needReset = el.multiple ? binding.value.some(function(v) { return hasNoMatchingOption(v, curOptions); }) : // 綁定值變化了,而且綁定值 匹配不到 options // hasNoMatchingOption 是匹配 某個值是否在數組中 binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, curOptions); if (needReset) { trigger(el, "change"); } } }
看源碼,這個鉤子大概做了兩件事
1、立即更新 selectedIndex
為什么要立即更新,怕 options 改變了,而 select.selectedIndex 沒有變,導致對應上了 新options 的 index 項,上錯花轎嫁對郎
[ 1,2,3 ] 選擇了第3項, 然后 index=2,值是3
然后 options 數據改變了,變成了 [7,8,9],而 index 還是2,而顯示值 變成了 9
很明顯這不符合邏輯啊,必須每次組件更新都要更新selectedIndex
2、更新綁定值
上面 componentUpdated 可以看到會手動觸發 change 回調
觸發的條件是
1、options 改變,而且跟舊options每個都不一樣
2、綁定值也改變
3、新綁定值無法在 新options 中匹配對應值
我也不懂為什么要調用一次 select 的 change 回調
要不我們 一起來查一下這個原由吧
首先,change 回調,作用是更新綁定值,難道就是為了更新?
我們寫個例子看一下
兩秒之后,會把 綁定值 和 options 同時改變,而且name并不存在arr 中
既然 一開始認為作用更新 綁定值,那我們看下綁定值更新成了什么鬼
變成了 undefined
的確是更新了綁定值哦,可是為什么要更新綁定值為 undefined 呢?想不通.....
上面是從內部去修改 綁定值的,我們從外部修改看一下,把內部修改的語句注釋掉
發現 外部修改綁定值,再改變 options ,外部修改的綁定值是不會隨著options變化而更新的哦
話說其實這里我沒太想通,也不知道自己想得對不對,感覺這里可以討論一下
根據上面的現象,我說出我的想法
我覺得尤大的想法是,從用戶角度出發
如果用戶沒有選擇任何option
但是 options 和 綁定值 同時改變,而且綁定值還不匹配options
這個綁定值改變有個毛用啊???
作為表單數據,你自己內部修改綁定值還不匹配任何option
這樣,用戶根本不知道你修改,他壓根沒選擇,而提交的時候,提交卻有數據,這是干毛?
舉栗子
選擇最愛的水果,options = [ 西瓜,香蕉,番茄 ]
你修改成了 options = [ 橙子,蘋果,雪梨 ],還把用戶的選擇值改成 錘子
用戶還不知道你修改了,我喜歡個錘子喜歡
沒道理啊是不是,所以最好是 重置為 undefined
也剛好符合 源碼的語義 needReset
額,我是這么想的,也不知道對不對,勿噴我,不過我覺得我的想法很有道理啊
如果用戶已經選擇option
就算options 改變了,那本質上也是沒有錯的,因為是用戶自己選擇,就算不匹配新options,所以就沒必要重置了
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105201.html
摘要:首先,兄弟,容我先說幾句涉及源碼很多,篇幅很長,我都已經分了上下三篇了,依然這么長,但是其實內容都差不多一樣,但是我還是毫無保留地給你了。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也...
摘要:因為失去焦點之后被強制更新了一波嗯,這就是的作用,把頁面上的顯示值也過濾一遍 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧 【Vue原理】VModel - 源碼版之input詳...
摘要:執行的時候,會綁定上下文對象為組件實例于是中的就能取到組件實例本身,的代碼塊頂層作用域就綁定為了組件實例于是內部變量的訪問,就會首先訪問到組件實例上。其中的獲取,就會先從組件實例上獲取,相當于。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之節點數據拼接上一篇我們 寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究...
閱讀 2915·2023-04-26 01:01
閱讀 3687·2021-11-23 09:51
閱讀 2519·2021-11-22 14:44
閱讀 3588·2021-09-23 11:57
閱讀 2832·2021-09-22 14:58
閱讀 5876·2021-09-10 11:25
閱讀 2104·2019-08-30 13:11
閱讀 1595·2019-08-30 12:59