国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【Vue原理】Compile - 源碼版 之 generate 拼接綁定的事件

OnlyMyRailgun / 2764人閱讀

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

寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟  


專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】

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

【Vue原理】Compile - 源碼版 之 generate 拼接綁定的事件

今天我們來(lái)探索事件的拼接啦,上一篇我們已經(jīng)講過(guò)了generate 階段 節(jié)點(diǎn)數(shù)據(jù)的拼接

事件也屬于其中一部分內(nèi)容,但是由于內(nèi)容實(shí)在太多太多太多太多,所以打算多帶帶拿出來(lái)講啦

這就是 Compile 的最后一篇文章了!終于終于發(fā)完了....真的發(fā)惡心了,估計(jì)網(wǎng)上找不著我這么詳細(xì)的 compile 文章了(找到當(dāng)我沒(méi)說(shuō))

本文章很長(zhǎng),一萬(wàn)多字,但是其實(shí)都是代碼和例子,幫助我們理解的,沒(méi)有什么,一路看下來(lái)絕壁沒(méi)有壓力,源碼也是簡(jiǎn)化過(guò)的

好吧,開(kāi)始正文

從上篇文章我們知道了,節(jié)點(diǎn)數(shù)據(jù)拼接,調(diào)用的是 genData$2 方法

現(xiàn)在我們就來(lái)回顧下這個(gè)方法(只保留了 事件 相關(guān))

function genData$2(el, state) {   



    var data = "{";


   .....已省略其他屬性拼接

   // 事件
   if(el.events) {
        data += genHandlers(el.events, false) + ",";
   } 

   // 原生事件
   if(el.nativeEvents) {
        data += genHandlers(el.nativeEvents, true) + ",";
   }



   data = data.replace(/,$/, "") + "}";   



   return data

}

沒(méi)錯(cuò),事件,分為 組件原生事件 和 事件

組件原生事件

顧名思義,就是給組件綁定的原生DOM事件,像這樣

事件

而這個(gè)呢,包含范圍很廣,包括 組件上的自定義事件,以及 標(biāo)簽上的原生事件,如下

他們調(diào)用的方法都是 genHandlers,都是把結(jié)果值直接拼接上 data ,那有什么不同呢?

不同就在于給 genHandlers 傳的最后一個(gè)參數(shù),現(xiàn)在我們把視角切到 genHandlers 方法上

genHandlers
function genHandlers(
    events, isNative

) {    

    var res = isNative ? "nativeOn:{": "on:{";    

    var handler = events[name]    



    for (var name in events) {

        res += ` ${name} : ${ genHandler(name,handler )} ,`
    }    



    return res.slice(0, -1) + "}"

}

這里非常明顯看到

當(dāng)你傳入 isNative=true 的時(shí)候,該事件即為 組件原生DOM 事件,需要拼接在 nativeOn:{} 字符串上

否則,就是事件,拼接在 on:{} 字符串上

先給個(gè)簡(jiǎn)單的例子來(lái)熟悉下

拼接后的字符串是這樣的

`_c("div", {
    on: { "click": aa }
},[
    _c("test", {
        on: { "test": cc },
        nativeOn: {
            "input":$event=>{
                return bb($event)
            }
        }
    })
])`

好的,大家大概有個(gè)了解了,下面我們將會(huì)探索事件內(nèi)部復(fù)雜的拼接了

因?yàn)樾枰婕暗礁鞣N許多的 modifiers

這次之前,先給大家介紹 Vue 內(nèi)部已經(jīng)設(shè)置了的按鍵值

按鍵內(nèi)部配置

Vue 把幾個(gè)常用的按鍵給配置了,當(dāng)然了,內(nèi)部設(shè)置的鍵名,你都是可以覆蓋配置的

很簡(jiǎn)單,過(guò)下眼,沒(méi)啥好說(shuō)的,不過(guò)下面會(huì)用到

記住,keyCodes 和 keyName 是 Vue 內(nèi)部配置鍵盤(pán)的變量

// 鍵盤(pán)和 code 映射

var keyCodes = {    

    esc: 27,  tab: 9,    

    enter: 13, space: 32,    

    up: 38, left: 37,    

    right: 39, down: 40,    

    delete: [8, 46]

};



// 鍵盤(pán)名映射

var keyNames = {    

    esc: "Escape",    

    tab: "Tab",    

    enter: "Enter",    

    space: " ",  // IE11 使用沒(méi)有 Arrow 前綴的鍵名

    up: ["Up", "ArrowUp"],    

    left: ["Left", "ArrowLeft"],    

    right: ["Right", "ArrowRight"],    

    down: ["Down", "ArrowDown"],    

    delete: ["Backspace", "Delete"]

};

看完了 Vue 的按鍵配置,我們來(lái)看 Vue 內(nèi)部配置的修飾符

修飾符內(nèi)部配置

相信大家在項(xiàng)目中,都有用到過(guò)修飾符吧,很方便對(duì)不對(duì),就是下面這些 stop prevent,很方便對(duì)不對(duì)

簡(jiǎn)直不要太方便,其實(shí) Vue 也沒(méi)做什么太多東西,不過(guò)是幫我們自動(dòng)組裝上了幾個(gè)語(yǔ)句

來(lái)看看 Vue 配置的修飾符

var modifierCode = {    

    stop: "$event.stopPropagation();",    

    prevent: "$event.preventDefault();",    

    ctrl: genGuard("!$event.ctrlKey"),    

    shift: genGuard("!$event.shiftKey"),   

    alt: genGuard("!$event.altKey"),    

    meta: genGuard("!$event.metaKey"),    

    self: genGuard("$event.target !== $event.currentTarget"),    

    left: genGuard(""button" in $event && $event.button !== 0"),    

    middle: genGuard(""button" in $event && $event.button !== 1"),    

    right: genGuard(""button" in $event && $event.button !== 2")

};

像 stop,prevent 直接就可以拼接在回調(diào)中

比如你綁定的事件名是 aaa 吼,并且使用了修飾符 stop,就會(huì)這么拼接

"function($event ){ " + 

    "$event.stopPropagation();" + 

    " return "+ aaa +"($event);" +

"}"

你肯定看到了其他修飾符使用了一個(gè)函數(shù) genGuard ,馬上看下

var genGuard = function(condition) {    

    return ` if ( ${ condition } ) return null `

}

這個(gè)函數(shù)炒雞簡(jiǎn)單,就是給你的事件回調(diào)拼接執(zhí)行條件(當(dāng)你使用了相關(guān)修飾符)

比如使用了 ctrl ,那么就會(huì)拼接上

if( !$event.ctrlKey ) return null

也就是說(shuō),當(dāng)你按的不是 ctrl 的時(shí)候,直接 return,不執(zhí)行下面

在比如一個(gè) middle,鼠標(biāo)中間,會(huì)拼接上

if( ""button" in $event && $event.button !== 1" ) 
return null

當(dāng)鼠標(biāo)點(diǎn)擊的按鍵不是 1 的時(shí)候,直接 return,不執(zhí)行下面(下面就會(huì)執(zhí)行你綁定的方法)

鍵盤(pán)修飾符

現(xiàn)在再來(lái)看看 Vue 是怎么給你拼接上按鍵的修飾符的吧,來(lái)看一個(gè)方法

這個(gè)方法,后面會(huì)用到,這里預(yù)言,記住哦

function genKeyFilter(keys) {    



    var key = keys.map(genFilterCode).join("&&")   



    return ` if( !("button" in $event) && ${ key } )
             return null `

}

這個(gè)方法跟前面的方法,拼接的內(nèi)容差不多,只是條件不一樣,條件是這樣

` if( !("button" in $event) && ${ key } )  
return null `

這個(gè) key 肯定是一個(gè)很重要的條件,怎么得到呢,兩個(gè)東西

keys,genFilterCode

現(xiàn)在一個(gè)個(gè)來(lái)說(shuō)一下

1參數(shù) keys

是一個(gè)數(shù)組,保存的是你添加的按鍵修飾符,可以是數(shù)字,可以是鍵名,比如

于是 keys = [ "enter" , 86 ],其中 enter 就是 enter 鍵,Vue 內(nèi)部定義過(guò),86 就是 鍵名 v 的值

然后會(huì)遍歷 keys,逐個(gè)調(diào)用 genFilterCode 去處理每個(gè)鍵值

現(xiàn)在看下它的源碼

2出現(xiàn)的函數(shù) genFilterCode
function genFilterCode(key) {    



    // 綁定的 modifier 是數(shù)字

    var keyVal = parseInt(key);    



    if (keyVal) {        

        return "$event.keyCode!==" + keyVal

    }    



    // 綁定的 modifier 是鍵名

    var keyCode = keyCodes[key];    

    var keyName = keyNames[key];  



    return `
        _k(
            $event.keyCode , 
            ${ key } , ${ keyCode }, 
            ${ $event.key } , ${ keyName }
        )
    `

}
如果參數(shù) key 是數(shù)字

這就簡(jiǎn)單了,直接 返回字符串

"$event.keyCode!==" + keyVal

于是回調(diào)就可以拼接上一個(gè)執(zhí)行條件,比如key 是數(shù)字 86

if( !("button in $event) && $event.keyCode!== 86 )  return null

這句話的意思就是當(dāng)你按下的鍵不是 86 的時(shí)候,就return,因?yàn)槟惚O(jiān)聽(tīng)的是 86 嘛,按其他鍵肯定是不執(zhí)行的啦

如果參數(shù) key 是鍵名

如果你的 key 是個(gè)名字,經(jīng)過(guò) parseInt 就變成 NAN,于是就走到下面一步了

哦吼,好像直接返回了呢,并且還從 keyName 和 keyCode 兩個(gè)對(duì)象中去獲取鍵值和鍵名

keyName 和 keyCode 前面已經(jīng)列出來(lái)了,就是兩個(gè)大對(duì)象,忘記可以翻上去看,Vue 內(nèi)部的變量,這里獲取會(huì)得到什么呢

比如你的鍵名是 enter, 獲取之后

那么 keyName = "Enter" , keyCode = 13

但是,這個(gè)鍵名不一定要存在 Vue 自己定義的 keyName 和 keyCode 中,所以你從這兩個(gè)變量中獲取也可能是 undefined

因?yàn)檫@個(gè)鍵名,你可以自定義

自定義鍵名

具體可以看官方文檔

https://cn.vuejs.org/v2/api/#...

3genFilterCode 返回值

我們現(xiàn)在來(lái)看看他的返回值

`_k(
    $event.keyCode ,    

    ${ key } , 

    ${ keyCode },

    $event.key , 

    ${ keyName }

)`

看著上面的字符串,我們一個(gè)個(gè)講

1 其中參數(shù)

五個(gè)參數(shù),key 就是你綁定的鍵名或鍵值,keyName 和 keyCode 上面講過(guò)了

剩下兩個(gè)參數(shù)

$event.keyCode / $event.key

$event 是事件對(duì)象,不用說(shuō)了

$event.keyCode 是你按下的鍵的值

$event.key 是你按下的鍵的名

比如你按下 v,事件對(duì)象就會(huì)包括這個(gè)鍵的信息

2 方法 _k 是什么

返回 _k 函數(shù)的話,比如按下 v,事件回調(diào)的執(zhí)行條件就變成

if( 
    !("button" in $event) &&
    _k(
        $event.keyCode ,        

        "v" , undefined,

        $event.key  , undefined
    )
)  return null

也就是說(shuō),每次按下鍵盤(pán),都會(huì)去調(diào)用一遍 _k 去檢查按鍵

_k 的本體其實(shí)是函數(shù) checkKeyCodes,源碼如下

function checkKeyCodes(
    eventKeyCode, key, keyCode, 
    eventKeyName, keyName

) {    



    // 比如 key 傳入的是自定義名字  aaaa

    // keyCode 從Vue 定義的 keyNames 獲取 aaaa 的實(shí)際數(shù)字
    // keyName 從 Vue 定義的 keyCode 獲取 aaaa 的別名
    // 并且以用戶定義的為準(zhǔn),可以覆蓋Vue 內(nèi)部定義的
    var mappedKeyCode = config.keyCodes[key] ||keyCode;    



    // 該鍵只在 Vue 內(nèi)部定義的 keyCode 中 

    if (keyName && eventKeyName && !config.keyCodes[key]) {        

        return isKeyNotMatch(keyName, eventKeyName)

    } 

    // 該鍵只在 用戶自定義配置的 keyCode 中
    else if (mappedKeyCode) {        

        return isKeyNotMatch(mappedKeyCode, eventKeyCode)

    } 

    // 原始鍵名
    else if (eventKeyName) {        

        return hyphenate(eventKeyName) !== key

    }
}

乍一看,好像很復(fù)雜?其實(shí)這個(gè)函數(shù)作用,就是檢查 key

比如你綁定 v,當(dāng)你按下 v 的時(shí)候,這個(gè)函數(shù)就返回 false

如果按下其他鍵,則返回 true,回調(diào)執(zhí)行條件為 真,所以就直接 return null,不會(huì)執(zhí)行下面綁定的回調(diào)

番外:"button" in $event

當(dāng)鼠標(biāo)按下的時(shí)候,這個(gè)表達(dá)式就為 true

而鍵盤(pán)按下的時(shí)候,事件對(duì)象不存在 button 這個(gè)值

所以 【!"button" in $event】 表示按鍵時(shí)必須沒(méi)有鼠標(biāo)按下

但是這個(gè)條件只有在【 非內(nèi)置修飾符 】才會(huì)存在,就是說(shuō) ctrl 那些鍵是沒(méi)有這個(gè)條件的

所以你可以綁定 click + ctrl 事件,比如

這么綁定時(shí)候,直接點(diǎn)擊是無(wú)效的,必須按下 ctrl 再點(diǎn)擊

但是你不能綁定 click + 普通按鍵,比如 click+v

就算你這么綁定了,也是沒(méi)用的,直接點(diǎn)擊也會(huì)觸發(fā) 而不用 v

下面現(xiàn)在我們繼續(xù)分析上面的 checkKeyCodes

1 config.keyCodes

這個(gè)就是你自己配置的鍵值鍵名表,下面是我的配置

2 函數(shù) isKeyNotMatch

檢查按下的鍵,是否【不和】 配置的鍵值對(duì) 匹配

function isKeyNotMatch(
    expect, actual

) {    



    if (Array.isArray(expect)) {        

        return expect.indexOf(actual) === -1

    } else {        

        return expect !== actual

    }
}

注意里面的匹配符是 ===-1 和 !== ,意思就是不匹配才返回 true,匹配則返回 false

比如你按下的鍵是 enter,Vue 內(nèi)部配置了 { enter:"Enter" }

而 參數(shù) actual 是調(diào)用 isKeyNotMatch 傳入的事件對(duì)象獲取的鍵名,也是 "Enter"

于是調(diào)用這個(gè)函數(shù)

isKeyNotMatch( "Enter" , "Enter" )

匹配成功,返回 false,也就是 checkKeyCode(_k) 返回false,回調(diào)執(zhí)行過(guò)濾條件為假,不會(huì) return null,這樣才會(huì)執(zhí)行下面

配置數(shù)組的話也是同理

3 出現(xiàn)的函數(shù) hyphenate
var hyphenate = function(str) {    
    return str.replace(/B([A-Z])/g, "-$1").toLowerCase()
}

把駝峰改成 - 命名

Vue 官方文檔說(shuō)了,不支持駝峰修飾符

4 checkKeyCodes 的 匹配順序

1、先匹配 Vue 內(nèi)部配置的鍵值對(duì)

但是要保證這個(gè)鍵不存在用戶重定義中,因?yàn)楸仨氁脩糇远x為主

2、匹配用戶自定義的鍵值對(duì)

3、匹配原始鍵值對(duì)

也就是說(shuō),你直接寫(xiě)鍵盤(pán)上的鍵名也是ok 的

像這樣,就綁定了 鍵 v 和 鍵 b

哎喲,我們已經(jīng)講了這么多啊,下面準(zhǔn)備開(kāi)始我們的主菜了

在一開(kāi)始的 genHandlers 中出現(xiàn)的女豬腳 genHandler,用于逐個(gè)處理 修飾符的 她

genHandler

這個(gè)函數(shù)有點(diǎn)長(zhǎng),用于處理修飾符,但是其實(shí)內(nèi)容并不復(fù)雜,邏輯也很清晰,但是第一眼肯定看得煩,雖然我已經(jīng)極大簡(jiǎn)化,你可以跳到后面的解析,對(duì)照著看一下

function genHandler(name,handler) {    



    // 沒(méi)有綁定回調(diào),返回一個(gè)空函數(shù)
    if (!handler) {        

        return "function(){}"

    }    



    // 如果綁定的是數(shù)組,則逐個(gè)遞歸一遍
    if (Array.isArray(handler)) {    
    

        return "[" + handler.map(handler) => {            

            return genHandler(name, handler);

        }).join(",") + "]"



    }    



    // 開(kāi)始解析單個(gè)回調(diào)

    var isMethodPath = simplePathRE.test(handler.value);    

    var isFunctionExpression = fnExpRE.test(handler.value);    



    // 沒(méi)有 modifier

    if (!handler.modifiers) {     

   

        // 是一個(gè)方法,或者有 function 關(guān)鍵字,可以直接作為回調(diào)
        if (isMethodPath || isFunctionExpression) {            

            return handler.value

        }        



        // 內(nèi)聯(lián)語(yǔ)句,需要包裹一層
        return "function($event){" + handler.value + ";}" 
    } 

    else {        



        var code = ""; // 保存按鍵修飾符

        var genModifierCode = ""; // 保存內(nèi)部修飾符
        var keys = [];        



        for (var key in handler.modifiers) { 

          

            if (modifierCode[key]) {

                ....被抽出,放在后面
            } 
            
            // 精確系統(tǒng)修飾符
            else if (key === "exact") {
                ....被抽出,放在后面
            } 

            // 普通按鍵
            else {
                keys.push(key);
            }
        }  

      

        // 開(kāi)始拼接事件回調(diào)!!!!



        // 拼接 Vue 定義外的按鍵修飾符
        if (keys.length) {
            code += genKeyFilter(keys);
        }   

    

        // 把 prevent 和 stop 這樣的修飾符在 按鍵過(guò)濾之后執(zhí)行

        if (genModifierCode) {
            code += genModifierCode;
        }        



        // 事件回調(diào)主體

        var handlerCode = 
              isMethodPath                



              // 執(zhí)行你綁定的函數(shù)

              ? "return " + handler.value + "($event)"
              : (
                  isFunctionExpression                    



                  // 如果回調(diào)包含 function 關(guān)鍵字,同樣執(zhí)行這個(gè)函數(shù)

                  ? "return " + handler.value + "($event)"
                  : handler.value;
              )        



        return ` function($event) { 

              ${ code + handlerCode }         
        } `

    }


}

下面開(kāi)始一點(diǎn)點(diǎn)解析上面的代碼

1出現(xiàn)的正則
// 包含function 關(guān)鍵字

var fnExpRE = /^([w$_]+|([^)]*?))s*=>|^functions*(/;



// 普通方法名

var simplePathRE = /^[A-Za-z_$][w$]*(?:.[A-Za-z_$][w$]*|["[^"]*?"]|["[^"]*?"]|[d+]|[[A-Za-z_$][w$]*])*$/;

不解釋這么多,直接看例子

fnExpRE 專門(mén)匹配有函數(shù)體的

simplePathRE 專門(mén)匹配函數(shù)名

所以其中的 isMethodPath 表示事件綁定的值 是否是函數(shù)名

isFunctionExpression 表示綁定值是否是 函數(shù)體

2綁定的 handler.modifiers

在 parse 階段,會(huì)把綁定的事件解析過(guò),所有的 modifiers 都解析成一個(gè)對(duì)象

比如

所以 handler.modifiers 可以直接遍歷而取到每一個(gè) 修飾符

3 收集內(nèi)部修飾符

這是被抽取的代碼

if (modifierCode[key]) {    

    // 拼接內(nèi)部的的事件修飾符

    genModifierCode += modifierCode[key];
}

先判斷這個(gè)修飾符是否存在 Vue 內(nèi)部的修飾符中

關(guān)于 modifierCode 可以看上面,已經(jīng)記錄過(guò)啦

比如吼

那么拼接修飾符吼,genModifierCode 就是

` 
  $event.stopPropagation(); 
  if( "button" in $event && $event.button !== 1" ) 
    return null

`
4收集系統(tǒng)修飾鍵 exact

或許你不知道什么是系統(tǒng)修飾鍵,我一開(kāi)始也不知道,看了源碼才知道有這個(gè)東西,如下的 exact

官方文檔地址:https://cn.vuejs.org/v2/guide...

在我的理解是,取消組合鍵的意思

比如你綁定了 按鍵 v,觸發(fā)的條件有幾個(gè)?

1、直接 按 v 鍵

2、ctrl + v 、 shift +v 、 alt +v 等等組合鍵

如果你添加了 exact 這個(gè)修飾符的話

那么觸發(fā)條件,只有你只按下這個(gè)鍵的時(shí)候才會(huì)觸發(fā),也就是說(shuō)一起按其他鍵無(wú)效

來(lái)看下從 genHandler 抽出的源碼

else if (key === "exact") {    



    var modifiers = handler.modifiers;


    genModifierCode +=

    genGuard(
        ["ctrl", "shift", "alt", "meta"]        



        // 過(guò)濾拿到?jīng)]寫(xiě) modifiers 的按鍵

        .filter(keyModifier = >{            

            return ! modifiers[keyModifier];

        })
    
        .map(keyModifier = >{            

            return "$event." + keyModifier + "Key"

        })

        .join("||")
    );
}

看源碼中,匹配的組合鍵有四個(gè)

ctrl , shift , alt ,meta

看源碼中,就是篩選出你沒(méi)有綁定的功能鍵

然后篩選出來(lái)的鍵被按下時(shí),直接 return null

比如你綁定了 ctrl,并使用了 exact

那么只有你【只按下】ctrl 的時(shí)候,才會(huì)觸發(fā)回調(diào)

看下拼接結(jié)果

` _c("input", {
    on: {
        "keyup" $event =>{

            if (!$event.ctrlKey) 

                return null;

            if ( $event.shiftKey || $event.altKey || $event.metaKey) 
                return null;

            return testMethod($event)
        }
    }
}) `

1、沒(méi)有按下 ctrl 的時(shí)候

2、按下了 ctrl的時(shí)候,但是也按下了 shfit 等其他功能鍵

同理,對(duì)于其他普通鍵也是一樣的,當(dāng)你不需要使用到組合鍵的時(shí)候,添加 exact 就好了

5收集其他按鍵
else{
    keys.push(key);
}

這是最普通的,當(dāng)你添加的修飾符,不在Vue內(nèi)部定義的修飾符中,也沒(méi)有 exact

那么就直接數(shù)組收集你添加的按鍵

比如

那么 keys = [ "v" , "b" ,"c" ]

6拼接事件回調(diào)

下面開(kāi)始本函數(shù)最重要的部分了,打起精神嘞

拼接事件回調(diào)的三個(gè)重點(diǎn)

1、拼接按鍵修飾符

2、拼接內(nèi)置修飾符

3、拼接事件回調(diào)

1 拼接按鍵修飾符
if (keys.length) {
    code += genKeyFilter(keys);
}

genKeyFilter 上面已經(jīng)講過(guò)了,忘記的可以回頭看看,這里給個(gè)結(jié)果就好了

比如

那么 keys = [ "v" , "b" ,"c" ]

最后拼接得到的 code 是

` if(
    !("button" in $event)&&
    _k($event.keyCode,"v",undefined,$event.key,undefined)&&
    _k($event.keyCode,"b",undefined,$event.key,undefined)&&
    _k($event.keyCode,"c",undefined,$event.key,undefined)
)
return null; `

調(diào)用了三個(gè) _k 函數(shù)

2 拼接內(nèi)部修飾符
if (genModifierCode) {
    code += genModifierCode;
}

genModifierCode 就是收集的 內(nèi)部修飾符 和 帶有 exact 的修飾符,上面有說(shuō)明

拼接結(jié)果是 code

` 
 $event.stopPropagation();
 if(!$event.shiftKey) return null;
`
3 拼接事件回調(diào)主體

這里開(kāi)始涉及到你綁定的回調(diào)了,你可以先嘗試看下源碼

var handlerCode = 

    isMethodPath    



    // 執(zhí)行你綁定的函數(shù)

    ? "return " + handler.value + "($event)"
    : (
        isFunctionExpression        



        // 如果回調(diào)包含 function 關(guān)鍵字,同樣執(zhí)行這個(gè)函數(shù)

        ? "return (" + handler.value + "($event))"
        : handler.value;
    )

1、如果你綁定的是方法名

比如你綁定的方法名是

那么 handlerCode 是

"return aaa($event)"`

2、如果有函數(shù)體

比如

那么 handlerCode 是

"return (function(){}($event))"

3、如果只是內(nèi)聯(lián)語(yǔ)句

比如

那么 handlerCode 是

aa = 33

直接把這條語(yǔ)句當(dāng)做 回調(diào)的一部分就好了

走流程

不知不覺(jué),我們已經(jīng)講了很多內(nèi)容,最后我們用一個(gè)例子去玩一下流程

收集內(nèi)置修飾符

1、拼接按鍵修飾符

2、拼接內(nèi)置修飾符

3、拼接事件回調(diào)

4、包裝事件回調(diào)

比如下面的模板,我們來(lái)看看怎么拼接事件

1、開(kāi)始遍歷修飾符

2、碰到 ctrl , 是內(nèi)置修飾符,收集起來(lái)
genModifierCode = ` 
    if( !$event.ctrlKey ) return null
 `
3、繼續(xù)遍歷,碰到 v,不是內(nèi)置,收集到 keys
keys.push("v")
4、遍歷結(jié)束,開(kāi)始拼接按鍵修飾符

調(diào)用 genKeyFilter ,傳入 keys,得到 code

code = `
    if(
        !("button" in $event)&&
        _k($event.keyCode,"v",undefined,$event.key,undefined)
    ) 
    return null;
`
5、把內(nèi)置修飾符放到 按鍵修飾符后面
code = code + genModifierCode
6、開(kāi)始拼接事件回調(diào),是個(gè)方法名
handlerCode = ` 
    return test($event)
 `
7、ok,最后一步,開(kāi)始組裝
` funciton($event){

    if( !$event.ctrlKey ) return null;

    if(
        !("button" in $event)&&
         _k($event.keyCode,"v",undefined,$event.key,undefined)
    )
    return null;

    return test($event)
}`

然后事件拼接就完成了!!!!!!!!!!

喲,別忘了,我們是要拼接到 render,趕快往上翻到 genHandlers

上面講的只是事件回調(diào),如果要拼接到 render 回調(diào),我們還要做下操作

加上事件名,拼接 on 對(duì)象字符串里面,像這樣,具體看上面的 genHandlers

`,on:{
    keyup: ...上面我們拼接的回調(diào)  } 

`

謝謝大家觀看,辛苦了

最后

鑒于本人能力有限,難免會(huì)有疏漏錯(cuò)誤的地方,請(qǐng)大家多多包涵,如果有任何描述不當(dāng)?shù)牡胤剑瑲g迎后臺(tái)聯(lián)系本人,領(lǐng)取紅包

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/106725.html

相關(guān)文章

  • Vue原理Compile - 源碼 generate 節(jié)點(diǎn)數(shù)據(jù)拼接

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

    fizz 評(píng)論0 收藏0
  • Vue原理Compile - 源碼 generate 節(jié)點(diǎn)拼接

    摘要:還原的難度就在于變成模板了,因?yàn)槠渌氖裁吹仁窃獠粍?dòng)的哈哈,可是直接照抄最后鑒于本人能力有限,難免會(huì)有疏漏錯(cuò)誤的地方,請(qǐng)大家多多包涵,如果有任何描述不當(dāng)?shù)牡胤剑瑲g迎后臺(tái)聯(lián)系本人,有重謝 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版...

    macg0406 評(píng)論0 收藏0
  • Vue原理Compile - 白話

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

    dingding199389 評(píng)論0 收藏0
  • Vue原理Compile - 源碼 optimize 標(biāo)記靜態(tài)節(jié)點(diǎn)

    摘要:一旦我們檢測(cè)到這些子樹(shù),我們可以把它們變成常數(shù),這樣我們就不需要了在每次重新渲染時(shí)為它們創(chuàng)建新的節(jié)點(diǎn)在修補(bǔ)過(guò)程中完全跳過(guò)它們。否則,吊裝費(fèi)用將會(huì)增加好處大于好處,最好總是保持新鮮。 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,...

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

    摘要:首先,兄弟,容我先說(shuō)幾句涉及源碼很多,篇幅很長(zhǎng),我都已經(jīng)分了上下三篇了,依然這么長(zhǎng),但是其實(shí)內(nèi)容都差不多一樣,但是我還是毫無(wú)保留地給你了。 寫(xiě)文章不容易,點(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

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

0條評(píng)論

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