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

資訊專欄INFORMATION COLUMN

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

fizz / 448人閱讀

摘要:寫(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í)吧
研究基于 Vue版本 【2.5.17】

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

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

上一篇我們講了不同節(jié)點(diǎn)的拼接,這一篇需要詳細(xì)記錄的是 節(jié)點(diǎn)數(shù)據(jù)的拼接

節(jié)點(diǎn)數(shù)據(jù),包括有 props,attrs,事件等

上一篇我們?cè)?genElement 中看到過(guò),每個(gè)節(jié)點(diǎn)都需要去拼接節(jié)點(diǎn)數(shù)據(jù),使用的就是下面源碼中的 genData$2 這個(gè)方法

function genElement() {

    .....處理其他類型的節(jié)點(diǎn)
    var data = genData$2(el, state);    

    var children = genChildren(el, state);


    code = `_c("${el.tag}", $ {
        data ? ("," + data) : ""
    }, $ {
        children ? ("," + children) : ""
    })`

}
genData$2

這個(gè)函數(shù)的源碼有點(diǎn)長(zhǎng),但是不用怕,都是處理各種屬性的判斷,所以內(nèi)容大約一致,不過(guò)里面涉及到具體的方法,會(huì)具體看

來(lái)吧,先過(guò)一遍把

function genData$2(el, state) {   



   var data = "{";   



   // 先解析指令

   var dirs = genDirectives(el, state);  



   // 拼接上解析得到的指令字符串
   if(dirs) {
        data += dirs + ",";
   }   



   // 帶有 is 綁定的組件,直接使用組件則沒(méi)有

   if(el.component) {
        data += `tag: ${el.tag} , ` 
   }   



   // 上一篇說(shuō)過(guò)的,dataGenFns 包含處理style,class的函數(shù)

   for(var i = 0; i < state.dataGenFns.length; i++) {
        data += state.dataGenFns[i](el);
   }   



   // 全部屬性

   if(el.attrs) {
        data += ` attrs:{ ${genProps(el.attrs)) } ,` 
   }  



   // 原生屬性

   if(el.props) {
        data += ` domProps:{ ${genProps(el.props)} }, ` 
   }   



    // 事件

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


   // 原生事件

   if(el.nativeEvents) {
        data += genHandlers(el.nativeEvents, true) + ",";
   }   



   // 沒(méi)有作用域的 slot

   if(
        el.slotTarget && !el.slotScope
    ) {
        data += ` slot: ${ el.slotTarget } ,` 
   }   



   // 作用域slot

   if(el.scopedSlots) {
        data += genScopedSlots(el.scopedSlots, state) + ",";
   }   



   // 組件使用 v-model

   if(el.model) {

        data += `model:{
            value:${el.model.value},
            callback:${el.model.callback},
            expression:${el.model.expression},
        },`
   }



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



   return data

}

首先這個(gè)方法,最終返回的是一個(gè)對(duì)象的序列化字符串,比如這樣

" { a:b , c:d } "

所以頭尾都會(huì) 加上大括號(hào),然后屬性拼接xx:yy 的形式

下面我們就來(lái)一個(gè)個(gè)看對(duì)于不同屬性的處理

拼接指令
function genDirectives(el, state) {    



    var dirs = el.directives;    



    if (!dirs) return

    var res = "directives:[";    

    var hasRuntime = false;    

    var i, l, dir, needRuntime;    



    for (i = 0, l = dirs.length; i < l; i++) {


        dir = dirs[i];
        needRuntime = true;        



        // 獲取到特定的 Vue 指令處理方法

        var gen = state.directives[dir.name];    

    

        // 如果這個(gè)函數(shù)存在,證明這個(gè)指令是內(nèi)部指令
        if (gen) {
            needRuntime = gen(el, dir);
        }        



        if (needRuntime) {


            hasRuntime = true;

            res += `{
                name: ${dir.name},
                rawName: ${dir.rawName}
                ${
                    dir.value
                    ? ",value:" + dir.value +", expression:" + dir.value    

                    : ""
                }
                ${ dir.arg ? ( ",arg:" + dir.arg ) : "" }
                ${
                    dir.modifiers
                    ? (",modifiers:" + JSON.stringify(dir.modifiers))
                    : ""
                }
            }, `

        }
    }    



    if (hasRuntime) {        

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

    }
}

首先呢,我們要了解這個(gè)方法會(huì)返回什么字符串,比如

就會(huì)返回這樣的字符串

`directives:[{
    name:"test",
    rawName:"v-test:a.b.c",
    value:222,
    expression:"arr",
    arg:"a",
    modifiers:{"b":true,"c":true}
}]`

每一個(gè)指令,都會(huì)解析成一個(gè)對(duì)象字符串,然后拼接在字符串?dāng)?shù)組里面

那么下面就來(lái)詳細(xì)記錄幾個(gè)可能疑惑的點(diǎn)

函數(shù)中出現(xiàn)的 state.directives

在上面文章中的 CodegenState 中,我們有寫(xiě)過(guò)這個(gè)

state.directives 是一個(gè)數(shù)組,包含了 Vue內(nèi)部指令的處理函數(shù),如下

v-on,v-bind,v-cloak,v-model ,v-text,v-html

函數(shù)中的變量 needRuntime

一個(gè)標(biāo)志位,表示是否需要把指令的數(shù)據(jù)解析成一個(gè) 對(duì)象字符串,像這樣

`{
    name:xxx, rawName:xxx,
    value:xxx, expression:xx,
    arg:xx, modifiers:xx
}`

也就是說(shuō),這個(gè)指令是否需要被拼接成 render 字符串中

那么什么指令需要,什么指令不需要呢?

自定義指令,都需要被解析,拼接在 render 字符串中

但是 Vue 的內(nèi)部指令,有的用,有的不用,所以就搞出一個(gè) needRunTime 來(lái)進(jìn)行判斷

Vue 的指令,先要獲取到特定的處理方法,賦值給 gen

gen 處理完返回 true,則表示需要 拼接上render,返回 false 或者不返回,則表示不需要拼接上

比如,v-model 指令的數(shù)據(jù)就需要拼接上 render,而 v-text,v-html 則不用

看下面的例子

比如上面的模板拼接成下面的字符串,發(fā)現(xiàn) v-html 并沒(méi)有出現(xiàn)在 directives 那個(gè)字符串?dāng)?shù)組中

`_c("div",{    

    directives:[{        

        name:"model",

        rawName:"v-model",        

        value:arr,

        expression:"arr"

    }],    

    domProps:{        

        "innerHTML":_s()

    }
})`
函數(shù)中的變量 hasRuntime

一個(gè)標(biāo)志位,表示是否需要把 return 指令字符串

genDirectives 處理的是一個(gè)指令數(shù)組,當(dāng)數(shù)組為空的時(shí)候,并不會(huì)有返回值

那么 render 字符串就不會(huì) 存在 directive 這一段字符串

如果指令不為空,那么 hasRunTime 設(shè)為 true,需要返回字符串

并且在 字符串尾部加上 ] , 這樣字符串?dāng)?shù)組就完整了

拼接組件

這里的解析組件,解析的是帶有 is 屬性的綁定組件

很簡(jiǎn)單,就是拼接上一個(gè) tag 的屬性就ok 了

看例子

原有的標(biāo)簽名,被拼接在 tag 后面

` _c("test",{tag:"div"}) `
拼接樣式

上篇文章也說(shuō)過(guò),state.dataGenFns 是一個(gè)數(shù)組

存放的是兩個(gè)函數(shù),一個(gè)是解析 class ,一個(gè)是解析 style 的

這里放下其中的源碼,非常的簡(jiǎn)單

解析 class
function genData(el) {    

    var data = "";    

    if (el.staticClass) {

        data += "staticClass:" + el.staticClass + ",";
    }   

    if (el.classBinding) {

        data += "class:" + el.classBinding + ",";
    }    

    return data

}
解析style
function genData$1(el) {    

    var data = "";    

    if (el.staticStyle) {

        data += "staticStyle:" + el.staticStyle + ",";
    }    

    if (el.styleBinding) {

        data += "style:(" + el.styleBinding + "),";
    }    

    return data

}

實(shí)在是太簡(jiǎn)單的,就是直接拼接上幾個(gè)屬性而已啦

給例子就好了

`_c("div",{
    staticClass:"a",
    class:name,
    staticStyle:{"height":"0"},
    style:{width:0}
})
`
拼接屬性

屬性的拼接只有一個(gè)函數(shù),內(nèi)容也十分簡(jiǎn)單

function genProps(props) {    



    var res = "";   



    for (var i = 0; i < props.length; i++) {        

        var prop = props[i];


        res += prop.name + ":" + 
               prop.value + ",";
    }    



    return res.slice(0, -1)

}

你可以看到,雖然只有一個(gè)方法,但是在 genData$2 中,拼接的結(jié)果會(huì)有兩種

拼接到 el.attr

拼接到 el.props

為什么會(huì)拼接到不同的地方?

因?yàn)榭吹氖悄銓傩?放的位置

如果你的屬性位置是 標(biāo)簽上,那么就會(huì)拼接到 attr 中

如果你的屬性位置是在 dom 上,那么就被拼接到 domProps 中

舉個(gè)例子

比如下面的模板,bbb 就是放在 標(biāo)簽上,aaa 就是放在 DOM 上

拼接的結(jié)果就是

` _c("div",{
    attrs:{"bbb":"bbb"},
    domProps:{"aaa":11}
}) `

頁(yè)面標(biāo)簽看不到 aaa

可以在 dom 屬性中找到 aaa

拼接事件

事件的拼接,內(nèi)容很多,打算放在另一篇文章詳細(xì)記錄

事件拼接還分為兩種,原生事件和 自定義事件,只是拼接為不同字符串而已,但是處理方法一樣

方法中涉及到各種 修飾符,哈哈,想知道到底為什么能寫(xiě)出這么方便的 api 呢哈哈

綁定按鍵,阻止默認(rèn)事件,直接這么寫(xiě)就行了

@keyup.enter.prevent="xxx"

歡迎觀看下篇文章

拼接普通Slot

就是直接拼接上 slot 這個(gè)屬性

` _c("test",[_c("span",{
        attrs:{"slot":"name"},
        slot:"name"
    })]
) `

如果組件有slot,沒(méi)有 slot 這個(gè)屬性,那么就不會(huì)拼接上slot,后面會(huì)直接給個(gè)默認(rèn)名字 “default”

拼接作用域Slot
function genScopedSlots(slots, state) {   



    return ` 
        scopedSlots:_u([${            

            Object.keys(slots).map(key =>{                

                return genScopedSlot(key, slots[key], state)
            })
            .join(",")
        }])
    `

}



function genScopedSlot(key, el, state) {  



    var fn = `
        function(${el.slotScope}){
            return ${
                el.tag === "template" 
                ? genChildren(el, state)
                : genElement(el, state)
            }
        }
    `

    return `{ key:${key} , fn: ${fn} }` 

}

這個(gè)處理作用域 slot 的函數(shù)看起來(lái)好像有一點(diǎn)復(fù)雜,但是其實(shí)就是紙老虎

不怕,先看一個(gè)實(shí)例

拼接成字符串,是這樣的

`  
  _c("div",{
     scopedSlots:_u([{
         key:"heder",
         fn:function(arr){return _c("div")}
     }])
  })
`

這個(gè)函數(shù)遍歷的是 el.scopeSlots 這個(gè)數(shù)組,或許你不知道這個(gè)數(shù)組是什么內(nèi)容?

同樣給個(gè)例子,這里有兩個(gè) slot

經(jīng)過(guò) parse 解析之后成一個(gè) ast,是這樣的

{    

    tag:"test",    

    scopedSlots:[{        

        slotScope: "arr"

        slotTarget: ""a""
        tag: "div"
    },{        

        slotScope: "arr"

        slotTarget: ""b""
        tag: "div"
    }]
}

沒(méi)錯(cuò),遍歷的就是上面對(duì)象里面的 scopedSlots 數(shù)組,數(shù)組中的每一項(xiàng)都是一個(gè)多帶帶的 slot

然后會(huì)使用 genScopeSlot 去多帶帶處理一下,上面有放出源碼

處理完之后,形成一個(gè)新的數(shù)組,genScopeSlot 也沒(méi)什么好說(shuō)的

拼接分類型,需要判斷 slot 位置的標(biāo)簽是不是 template

如果是template,那么他的真實(shí)slot 是 template 的子節(jié)點(diǎn),直接獲取他的子節(jié)點(diǎn)

如果不是template,那么本身就是真實(shí)的slot

因?yàn)?template 是Vue 自帶的一個(gè) 模板節(jié)點(diǎn),是不存在的

拼接組件VModel

沒(méi)錯(cuò),這里的 model,只是屬于 組件的 v-model

if (el.model) {

    data += `model: {
        value: $ { el.model.value },
        callback: $ { el.model.callback },
        expression: $ { el.model.expression },
    }, `

}

官網(wǎng)說(shuō)了這個(gè)是怎么用的

一個(gè)組件上的 v-model 默認(rèn)會(huì)利用名為 value 的 prop 和名為 input 的事件

也就是說(shuō),起始就是給組件傳了一個(gè) value,綁定了一個(gè)事件 input

也沒(méi)有什么好講的,記錄下組件的 v-model 是這么拼接就好了

例子

經(jīng)過(guò) parse 解析,得到 ast

{    

    tag: "test",    

    model:{        

        callback: "function ($$v) {num=$$v}"

        expression: ""num""
        value: "num"
    }
}

拼接成字樣變成字符串了

` 
  _c("test",{
      model:{
          value:num,
          callback:function ($$v) {num=$$v},
          expression:"num"
      }
  })
`
舉個(gè)栗子

屬性拼接呢,我們就講完了,最后我們來(lái)看一個(gè)例子吧

下面這個(gè)模板,我們把它拼接起來(lái)

解析成下面這個(gè) render 字符串,看懂了,你就掌握了 generate 的內(nèi)容了

以后你就可以去看別人用Vue 寫(xiě)的打包后的代碼了

甚至,你可以手動(dòng)還原他,如果你閑得很,你可以自己寫(xiě)個(gè)方法,傳入render 字符串,自動(dòng)還原成 template 模板

` _c("div", {
    attrs: {
        "b": "2"
    },
    domProps: {
        "a": 11
    }
},[
    _c("test", {

       scopedSlots: _u([{
          key: "a",
          fn: function(arr) {
              return _c("strong")
          }
      }]),

      model: {
          value: (num),
          callback: function($$v) {
              num = $$v
          },
          expression: "num"
      }

    },[_c("span")])
]) `
最后

鑒于本人能力有限,難免會(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://m.specialneedsforspecialkids.com/yun/106697.html

相關(guān)文章

  • 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 - 源碼 generate 拼接綁定的事件

    摘要:寫(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í)吧研究...

    OnlyMyRailgun 評(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原理Compile - 源碼 從新建實(shí)例到 compile結(jié)束的主要流程

    摘要:頁(yè)面這個(gè)實(shí)例,按理就需要解析兩次,但是有緩存之后就不會(huì)理清思路也就是說(shuō),其實(shí)內(nèi)核就是不過(guò)是經(jīng)過(guò)了兩波包裝的第一波包裝在中的內(nèi)部函數(shù)中內(nèi)部函數(shù)的作用是合并公共和自定義,但是相關(guān)代碼已經(jīng)省略,另一個(gè)就是執(zhí)行第二波包裝在中,目的是進(jìn)行緩存 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 ...

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

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

0條評(píng)論

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