成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【Vue原理】VModel - 源碼版之input詳解

leanxi / 2911人閱讀

摘要:因?yàn)槭ソ裹c(diǎn)之后被強(qiáng)制更新了一波嗯,這就是的作用,把頁(yè)面上的顯示值也過(guò)濾一遍

寫文章不容易,點(diǎn)個(gè)贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】

如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧

【Vue原理】VModel - 源碼版之input詳解

上一篇文章,我們大概講了所有表單元素的雙綁原理,但是仍然有兩個(gè)特殊的表單元素,是要多更多處理的,也不可能放在一篇文章說(shuō)完,今天,我們說(shuō)的是 input 的特殊處理的地方

而 input 有什么特殊處理的地方呢?

1、預(yù)輸入延遲更新

2、range 類型的 input

3、v-model.lazy

4、v-model.trim、v-model-number

預(yù)輸入延遲更新

先來(lái)看看Vue 給 input 正常綁定的回調(diào)

input: function($event) {     
    if ($event.target.composing) return;
    name = $event.target.value
}

看到我標(biāo)紅的地方,這句話就是完成預(yù)輸入延遲更新的重點(diǎn)

當(dāng)composing=true時(shí),事件回調(diào)不會(huì)走到下面的更新操作,而 Vue 正式通過(guò)這個(gè)標(biāo)志位,判斷現(xiàn)在是否是預(yù)輸入而確定是否需要實(shí)時(shí)更新

首先,Vue 會(huì)為 input 或者 textarea 綁定以下事件

compositionstart
compositionend
change
開始講解這三個(gè)事件了

1、compositionstart

首先,compositionstart 會(huì)在 input 事件觸發(fā)之前 觸發(fā)

but!你打一些直接輸入的字符,是不會(huì)觸發(fā) compositionstart 的,只會(huì)觸發(fā) input

只有打預(yù)輸入的字符才會(huì)觸發(fā),比如 輸入拼音,不行看圖

輸入普通字符

預(yù)輸入延遲更新下,輸入拼音

取消預(yù)輸入延遲更新,輸入拼音

看完上面的動(dòng)圖,預(yù)輸入延遲更新什么用,估計(jì)你心里也有點(diǎn)逼數(shù)了吧?

為什么要做預(yù)輸入延遲更新?

如果不做!在輸入拼音的時(shí)候,每打一個(gè)拼音字母都會(huì)觸發(fā) input 事件,但是我們根本還沒(méi)往表單中寫入我們預(yù)想中的東西

而此時(shí)觸發(fā) input 事件沒(méi)有任何意義,因?yàn)檫€不是我們要輸入的值,這是一個(gè)浪費(fèi)的操作

剛好,compositionstart 在 input 之前觸發(fā),而且只會(huì)預(yù)輸入才觸發(fā)

所以!就可以通過(guò)一個(gè)標(biāo)志位來(lái)控制 input 回調(diào)導(dǎo)致的更新就再好不過(guò)了!

怎么做呢?看 compositionstart 回調(diào)源碼

function onCompositionStart(e) {
    e.target.composing = true;
}

2、compositionend

在打完預(yù)輸入的字符之后,會(huì)觸發(fā)

在預(yù)輸入延遲更新中起什么作用呢?

預(yù)輸入結(jié)束,肯定是設(shè)置 composing 為 false了,看源碼

function onCompositionEnd(e,eventname) {    
    if (!e.target.composing) { return }
    e.target.composing = false;
    trigger(e.target, "input");
}

還會(huì) 手動(dòng)觸發(fā) input 事件去 執(zhí)行更新操作哦

trigger 是什么?也是很簡(jiǎn)單的,值得收藏的源碼,不解釋了

function trigger(el, type) {    
    var e = document.createEvent("HTMLEvents");
    e.initEvent(type, true, true);
    el.dispatchEvent(e);
}

3、change

為了兼容Safari<10.2 等那些 不會(huì)觸發(fā) compositionend 的瀏覽器(Vue自己注釋說(shuō)的,我沒(méi)有測(cè)過(guò)),于是監(jiān)聽(tīng) change事件,來(lái)代替 compositionend 的功能

change 的回調(diào) 和 compositionend 的回調(diào)是一樣的,因?yàn)橹皇且粋€(gè)備胎功能

4、 他們?cè)谀睦镩_始綁定這些事件呢?

你應(yīng)該必須知道,指令都是有生命鉤子函數(shù)的,而這幾個(gè)事件正是在 inserted 鉤子中進(jìn)行綁定的

Vue 官方文檔說(shuō)明 inserted

看下 inserted 鉤子函數(shù)

function inserted(el, binding, vnode, oldVnode) {   

    // isTextInputType判斷 input 是不是 text,number,password,search,email,tel,url其中一個(gè)
    if (vnode.tag === "textarea" || isTextInputType(el.type)) {
        el._vModifiers = binding.modifiers;        
        // 如果設(shè)置 v-model.lazy,那么不處理 預(yù)輸入的問(wèn)題
        if (!binding.modifiers.lazy) {
            el.addEventListener("compositionstart", onCompositionStart);
            el.addEventListener("compositionend", onCompositionEnd);
            el.addEventListener("change", onCompositionEnd);
        }
    }
}

TIP

inserted 鉤子中,還處理了 select ,但是這里是input的版塊,所以去掉了,放在下篇文章講

Range 類型 Input

為了兼容 IE,所以在解析的時(shí)候,先保存的是 __r 事件,后面開始綁定的時(shí)候,判斷瀏覽器而決定使用什么事件

function genDefaultModel(
    el, value,  modifiers

){    
    var type = el.attrsMap.type;    
    var ref = modifiers || {};    
    var lazy = ref.lazy;   

    // 這里省略了lazy 的判斷啦
    var event = type === "range" ? "__r" :"input";

    code = "if($event.target.composing)return;" 
            + value+"=$event.target.value";
    addProp(el, "value", ("(" + value + ")"));
    addHandler(el, event, code, null, true);
}

看到我加藍(lán)加粗的地方,就是為 range 特別處理的地方,綁定 __r 事件

判斷瀏覽器,轉(zhuǎn)換事件的函數(shù)updateDOMListeners源碼

function updateDOMListeners(oldVnode, vnode) {    

    var on = vnode.data.on    
    if (isDef(on["__r"])) {        
        var event = isIE ? "change": "input";
        on[event] = [].concat(on["__r"], on[event] || []);        
        delete on["__r"];
    }    
    for (name in on) {
        vnode.elm.addEventListener(name, on[name]);
    }
}
v-model.lazy

當(dāng)你的 v-model 設(shè)置了 lazy 的時(shí)候,會(huì)綁定 change 而不是 input,延時(shí)更新的意思

function genDefaultModel(
    el, value, modifiers

){    

    var ref = modifiers || {};    
    var lazy = ref.lazy;    

    // 省略了 range 類型的判斷
    var event = lazy ? "change" :"input";
    addHandler(el, event, code, null, true);
}

我們都知道,為了輸入實(shí)時(shí)響應(yīng),vue 默認(rèn)為 input 等輸入類型的 表單 綁定 input 事件,讓 input

如果你設(shè)置延遲更新,就是相當(dāng)于你改變了內(nèi)容,然后失去焦點(diǎn)才觸發(fā)

v-model.trim、v-model.number

如果你給 v-model 設(shè)置了值過(guò)濾,像 trim 去掉首尾空格,number 把值變成數(shù)字

function genDefaultModel(
   el, value, modifiers
){    

    var ref = modifiers || {}; 
    var number = ref.number;    
    var trim = ref.trim;  


    // 去首尾空格
    if (trim) {
        valueExpression = "$event.target.value.trim()";
    }    

    // 轉(zhuǎn)成數(shù)字
    if (number) {
        valueExpression = "_n(" + valueExpression + ")";
    }
    
    code = "if($event.target.composing)return;" +
            value+"="+valueExpression;
    
    addProp(el, "value", ("(" + value + ")"));
    addHandler(el, "input", code, null, true); 
    
    if (trim || number) {
        addHandler(el, "blur", "$forceUpdate()");
    }   

} 

對(duì)于 trim 和 number,Vue 會(huì)對(duì)表單值做處理,你可以看到源碼中

trim:值會(huì)調(diào)用 trim 方法

number:會(huì)調(diào)用 _n 轉(zhuǎn)換成數(shù)字方法

看下最終的回調(diào)

function($event){

if($event.target.composing)return;
name=_n($event.target.value);

}

function($event){    
    if($event.target.composing)return;
    name=$event.target.value.trim();
}

這兩個(gè)鬼東西,還會(huì)額外綁定一個(gè)事件 blur

看下回調(diào) $forceUpdate,這個(gè)函數(shù)作用是強(qiáng)制更新頁(yè)面

為什么要更新頁(yè)面?給個(gè)動(dòng)圖看好吧

我設(shè)置了 trim,然后輸入的時(shí)候,故意多加幾個(gè)空格,然后失去焦點(diǎn)(觸發(fā)設(shè)置的 blur),再點(diǎn)發(fā)現(xiàn)空格不見(jiàn)了。因?yàn)槭ソ裹c(diǎn)之后被強(qiáng)制更新了一波

嗯,這就是 $forceUpdate 的作用,把頁(yè)面上的顯示值也過(guò)濾一遍

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105202.html

相關(guān)文章

  • Vue原理VModel - 源碼版 之 select 詳解

    摘要:寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧原理源碼版之詳解今天我們來(lái)看看處 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 ...

    lsxiao 評(píng)論0 收藏0
  • Vue原理VModel - 源碼版 之 表單元素綁定流程

    摘要:首先,兄弟,容我先說(shuō)幾句涉及源碼很多,篇幅很長(zhǎng),我都已經(jīng)分了上下三篇了,依然這么長(zhǎng),但是其實(shí)內(nèi)容都差不多一樣,但是我還是毫無(wú)保留地給你了。 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也...

    sarva 評(píng)論0 收藏0
  • Vue原理VModel - 白話版

    摘要:執(zhí)行的時(shí)候,會(huì)綁定上下文對(duì)象為組件實(shí)例于是中的就能取到組件實(shí)例本身,的代碼塊頂層作用域就綁定為了組件實(shí)例于是內(nèi)部變量的訪問(wèn),就會(huì)首先訪問(wèn)到組件實(shí)例上。其中的獲取,就會(huì)先從組件實(shí)例上獲取,相當(dāng)于。 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得...

    keke 評(píng)論0 收藏0
  • Vue原理】依賴收集 - 源碼版之基本數(shù)據(jù)類型

    摘要:當(dāng)東西發(fā)售時(shí),就會(huì)打你的電話通知你,讓你來(lái)領(lǐng)取完成更新。其中涉及的幾個(gè)步驟,按上面的例子來(lái)轉(zhuǎn)化一下你買東西,就是你要使用數(shù)據(jù)你把電話給老板,電話就是你的,用于通知老板記下電話在電話本,就是把保存在中。剩下的步驟屬于依賴更新 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【...

    VincentFF 評(píng)論0 收藏0
  • Vue原理】Slot - 源碼版之普通插槽

    摘要:我們都知道分為普通和作用域,兩個(gè)內(nèi)容都很多,所以分兩部分進(jìn)行講述。今天講的是普通其實(shí)普通,表示默認(rèn)和具名,只是他們的處理方式都差不多,就只是是否有自定義名字而已,所以,表示一種類型。 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,請(qǐng)...

    lansheng228 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<