久久精品中文字幕免费_91香蕉国产亚洲一区二区三区_国产精品巨作无遮拦_亚洲人成电影

    <center id="oy65s"><ol id="oy65s"></ol></center>

  • <menu id="oy65s"></menu>
    當(dāng)前位置:首頁 > 足球資訊 > 正文內(nèi)容

    Vue0.11版本源碼閱讀系列四:詳解指令值解析函數(shù)

    杏彩體育2年前 (2023-01-28)足球資訊49

    需求

    首先該版本的vue指令值支持一下幾種類型以及通過dirParser.parse要返回的數(shù)據(jù):

    1.實例屬性:message,解析后應(yīng)為:

    [ { "raw":"message", "expression":"message" } ]

    2.表達(dá)式:message === show,解析后應(yīng)為:

    [ { "raw":"message === show", "expression":"message === show" } ]

    3.三元表達(dá)式:show ? true : false,解析后應(yīng)為:

    [ { "raw":"message === show ? true : false", "expression":"message === show ? true : false" } ]

    4.設(shè)置元素類名、樣式、屬性、事件的:red:hasError,bold:isImportant,hidden:isHidden,解析后應(yīng)為:

    [ {"arg":"red","raw":"red: hasError","expression":"hasError"}, {"arg":"bold","raw":"bold: isImportant","expression":"isImportant"}, {"arg":"hidden","raw":"hidden: isHidden","expression":"isHidden"} ]

    或者:top: top + px,left: left + px,background-color: rgb(0,0, + bg + ),解析后應(yīng)為:

    [ {"arg":"top","raw":"top: top + px","expression":"top + px"}, {"arg":"left","raw":"left: left + px","expression":"left + px"}, {"arg":"background-color","raw":"background-color: rgb(0,0, + bg + )","expression":"rgb(0,0, + bg + )"} ]

    5.雙大括號插值的:{{partialId}},解析后應(yīng)為:

    [ { "raw":"{{partialId}}", "expression":"{{partialId}}" } ]

    6.指令值是數(shù)組或?qū)ο?/p>

    [1, 2, 3]應(yīng)解析為:

    [ { "raw":"[1, 2, 3]", "expression":"[1, 2, 3]" } ]

    {arr: [1, 2, 3], value: abc}應(yīng)解析為:

    [ { "raw":"{arr: [1, 2, 3], value: abc}", "expression":"{arr: [1, 2, 3], value: abc}" } ]

    7.過濾器:

    message | capitalize應(yīng)解析為:

    [ { "expression":"message", "raw":"message | capitalize", "filters":[ { "name":"capitalize", "args":null } ] } ]

    帶參數(shù)的message | capitalize 4 5應(yīng)解析為:

    [ { "expression":"message", "raw":"message | capitalize 4 5", "filters":[ { "name":"capitalize", "args":["4","5"] } ] } ]

    多個過濾器之間使用|進行分隔。

    總結(jié)一下,就是如果是以逗號分隔的冒號表達(dá)式,則解析為:

    [ { arg: 【冒號前的字符】, expression: 【冒號后的字符】, raw: 【原始值】 }, ... ]

    帶過濾器的會多一個filters字段。

    其他一律解析為:

    [ { expression: 【和原始值一樣的值】, raw: 【原始值】 } ]

    實現(xiàn)

    現(xiàn)在讓我們從0開始寫一個解析器:

    let dirs = [] function parse(s) { return dirs }

    簡單的變量

    首先支持最簡單的第一種,實例屬性或方法,根據(jù)上面的對照,基本原封不動返回即可:

    var str = var dirs = [] var dir = {} var begin = 0 var i = 0 exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) {} pushDir() return dirs } function pushDir () { dir.raw = str.slice(begin, i) dir.expression = str.slice(begin, i) dirs.push(dir) }

    可以看到完全就是為了得到目標(biāo)值的一個多此一舉的過程,下一步來支持逗號分隔的冒號表達(dá)式。

    冒號表達(dá)式

    先看就一個的情況,如a:b,遍歷到的當(dāng)前字符如果是冒號的話就把冒號之前的字符截取出來作為arg,冒號后的字符作為expression,begin變量是用來標(biāo)記當(dāng)前這個表達(dá)式的起點的,所以要截取冒號后的字符需要新增一個變量:

    var str = var dirs = [] var dir = {} var begin = 0 var argIndex = 0 // ++ var i = 0 exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) { // ++ c = str.charCodeAt(i) if (c === 0x3A) {// 冒號: dir.arg = str.slice(begin, i).trim() argIndex = i + 1 } } pushDir() return dirs } function pushDir () { dir.raw = str.slice(begin, i) dir.expression = str.slice(argIndex, i).trim()// ++ dirs.push(dir) }

    接下來支持存在逗號的情況,逗號相當(dāng)于一個表達(dá)式的結(jié)束,所以要進行一次push,另外begin、argIndex、dir變量都需要重置:

    exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) if (c === 0x3A) {// 冒號: dir.arg = str.slice(begin, i).trim() argIndex = i + 1 } else if (c === 0x2C) {// 逗號, ++ pushDir() dir = {} begin = argIndex = i + 1 } } pushDir() return dirs }

    三元表達(dá)式

    接下來支持三元表達(dá)式,目前會把三元表達(dá)式的冒號前后部分分離調(diào),會輸出類似下面的結(jié)果:

    [ { "arg":"show ? true", "raw":"show ? true : false", "expression":"false" } ]

    所以檢查到冒號的時候我們要判斷一下這是否是個三元表達(dá)式,是的話就不截?。?/p>exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) if (c === 0x3A) {// 冒號: ++ var arg = str.slice(begin, i).trim() if (/^[^\?]+$/.test(arg)) { dir.arg = arg argIndex = i + 1 } } else if (c === 0x2C) { pushDir() dir = {} begin = argIndex = i + 1 } } pushDir() return dirs }

    判斷一下冒號之前的字符里是否存在?,存在的話就代表是三元表達(dá)式,則不進行分割。

    看一個特殊情況:background-color: rgb(0,0, + bg + )

    目前會解析成:

    [ { "arg":"background-color", "raw":"background-color: rgb(0", "expression":"rgb(0" }, { "raw":"0", "expression":"0" }, { "raw":" + bg + )", "expression":" + bg + )" } ]

    原因就出在屬性值里的逗號,如果屬性值里存在逗號,那該屬性值一定是被引號包圍的,所以在單引號或雙引號里的都要忽略,所以讓我們新增兩個變量來記錄是否是在引號里:

    var inDouble = false // ++ var inSingle = false // ++

    如果出現(xiàn)第一個引號,把標(biāo)志設(shè)為true,然后中間字符都直接跳過,直到出現(xiàn)閉合的引號,才退出繼續(xù)其他的判斷:

    exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) if (inDouble) {// 雙引號還未閉合 ++ if (c === 0x22) {// 出現(xiàn)了閉合引號 inDouble = !inDouble } } else if (inSingle) {// 單引號還未閉合 ++ if (c === 0x27) {// 出現(xiàn)了閉合引號 inSingle = !inSingle } } else if (c === 0x3A) { // ... } else if (c === 0x2C) { // ... } else {// ++ switch (c) { // 首次出現(xiàn)引號設(shè)置標(biāo)志位 case 0x22: inDouble = true; break // " case 0x27: inSingle = true; break // default: break; } } } pushDir() return dirs }

    數(shù)組或?qū)ο?/h2>

    數(shù)組或?qū)ο蠖夹枰獠粍拥姆祷?,因為帶冒號和逗號目前都會被切割,對?shù)組來說,字符都是被[]中括號包圍的,所以在這區(qū)間的逗號要忽略掉,因為括號可能多重嵌套,所以增加一個變量來計數(shù),出現(xiàn)左括號加1,出現(xiàn)右括號減1,為0就代表不在括號里:

    var square = 0// ++ exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) if (inDouble) {} else if (inSingle) {} else if (c === 0x3A) {} else if (c === 0x2C && square === 0) {// ++ pushDir() dir = {} begin = argIndex = i + 1 } else { switch (c) { case 0x22: inDouble = true; break case 0x27: inSingle = true; break case 0x5B: square++; break // [ ++ case 0x5D: square--; break // ] ++ default: break; } } } pushDir() return dirs }

    對象也是類似,但是對象多了冒號,冒號也會被截掉,所以需要和三元表達(dá)式一樣進行判斷:

    var curly = 0// ++ exports.parse = function (s) { str = s for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) if (inDouble) {} else if (inSingle) {} else if (c === 0x3A) { var arg = str.slice(begin, i).trim() if (/^[^\?\{]+$/.test(arg)) {// ++ 正則表達(dá)式修改,如果出現(xiàn)了{(lán)代表可能是對象 dir.arg = arg argIndex = i + 1 } } else if (c === 0x2C && square === 0 && curly === 0) {// ++ pushDir() dir = {} begin = argIndex = i + 1 } else { switch (c) { // ... case 0x7B: curly++; break // { ++ case 0x7D: curly--; break // } ++ default: break; } } } pushDir() return dirs }

    過濾器

    最后來看過濾器,過濾器使用管道符|,所以遍歷到這個字符時推入過濾器,過濾器支持多個,第一個字符串代表表達(dá)式,后續(xù)|分隔的各代表一個過濾器,當(dāng)出現(xiàn)第一個|時只能獲取到該過濾器所被應(yīng)用的值,也就是expression的值,需要繼續(xù)遍歷才知道具體的過濾器,如何判斷是否是第一個|可以根據(jù)expression是否有值:

    exports.parse = function (s) { for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) // ... else if (c === 0x7C) {// 管道符| if (dir.expression === undefined) {// 第一次出現(xiàn)| dir.expression = str.slice(argIndex, i).trim()// 截取第一個|前的字符來作為表達(dá)式的值 } } // ... } } function pushDir () { dir.raw = str.slice(begin, i) if (dir.expression === undefined) {// ++ 這里也需要進行判斷,如果有值代表已經(jīng)被過濾器分支設(shè)置過了,這里就不需要設(shè)置 dir.expression = str.slice(argIndex, i).trim() } dirs.push(dir) }

    假設(shè)只有一個過濾器的話繼續(xù)遍歷會直到結(jié)束,結(jié)束后會再調(diào)一次pushDir方法,所以修改一下這個方法,進行一次過濾器收集處理:

    function pushDir () { dir.raw = str.slice(begin, i) if (dir.expression === undefined) { dir.expression = str.slice(argIndex, i).trim() } else {// ++ 添加過濾器 pushFilter() } dirs.push(dir) } function pushFilter () { // 這里要截取的字符串應(yīng)該是|后面的,begin和argIndex字段都用不了,所以需要新增一個變量 }

    新增一個變量用于記錄當(dāng)前過濾器的起始位置:

    var lastFilterIndex = 0 // ++ exports.parse = function (s) { for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) // ... else if (c === 0x7C) { if (dir.expression === undefined) { dir.expression = str.slice(argIndex, i).trim() } lastFilterIndex = i + 1// ++ } // ... } }

    因為過濾器支持帶參數(shù),參數(shù)和過濾器名之間用空格分隔,所以寫一個正則來匹配一下:/[^\s"]+|[^]+|"[^"]+"/g,參數(shù)除了是變量也可以是字符串,所以后面兩個對引號的匹配是為了保證最后匹配的結(jié)果也是帶引號的,否則:capitalize abc和capitalize abc最后匹配出來的都是:["abc"],加上后面兩個引號的匹配后則才是我們需要的:["abc"]。

    function pushFilter() { var exp = str.slice(lastFilterIndex, i).trim() if (exp) { var tokens = exp.match(/[^\s"]+|[^]+|"[^"]+"/g) var filter = {} filter.name = tokens[0] filter.args = tokens.length > 1 ? tokens.slice(1) : null dir.filters = dir.filters || [] dir.filters.push(filter) } }

    結(jié)果如下:

    接下來支持一下多個過濾器的情況,多個過濾器,則會出現(xiàn)多個|,所以又會走到|的if分支,非第一次出現(xiàn)的話不需要修改expression的值,直接push當(dāng)前遍歷到的過濾器即可:

    exports.parse = function (s) { for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) // ... else if (c === 0x7C) { if (dir.expression === undefined) { dir.expression = str.slice(argIndex, i).trim() } else {// 非第一次出現(xiàn)直接push ++ pushFilter() } lastFilterIndex = i + 1 } // ... } }

    結(jié)果如下:

    最后也看一種特殊情況,就是||的情況,這是或的意思,所以肯定不能解析為過濾器,在if條件里增加一下判斷,排除當(dāng)前遍歷到的|前一個或后一個字符也是|的情況:

    exports.parse = function (s) { for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) // ... else if (c === 0x7C && str.charCodeAt(i - 1) !== 0x7C && str.charCodeAt(i + 1) !== 0x7C) {// ++ // ... } // ... } }

    完成

    到這里基本就完成了,完整代碼如下:

    var str = var dirs = [] var dir = {} var begin = 0 var argIndex = 0 var i = 0 var inDouble = false var inSingle = false var square = 0 var curly = 0 var lastFilterIndex = 0 function reset() { str = dirs = [] dir = {} begin = 0 argIndex = 0 i = 0 inDouble = false inSingle = false square = 0 curly = 0 lastFilterIndex = 0 } exports.parse = function (s) { reset() str = s for (i = 0, l = str.length; i < l; i++) { c = str.charCodeAt(i) if (inDouble) {// 雙引號還未閉合 if (c === 0x22) {// 出現(xiàn)了閉合引號 inDouble = !inDouble } } else if (inSingle) {// 單引號還未閉合 if (c === 0x27) {// 出現(xiàn)了閉合引號 inSingle = !inSingle } } else if (c === 0x3A) {// 冒號: var arg = str.slice(begin, i).trim() if (/^[^\?\{]+$/.test(arg)) { dir.arg = arg argIndex = i + 1 } } else if (c === 0x2C && square === 0 && curly === 0) {// 逗號, pushDir() dir = {} begin = argIndex = i + 1 } else if (c === 0x7C && str.charCodeAt(i - 1) !== 0x7C && str.charCodeAt(i + 1) !== 0x7C) {// 管道符| if (dir.expression === undefined) {// 第一次出現(xiàn)| dir.expression = str.slice(argIndex, i).trim() } else {// 非第一次出現(xiàn)直接push pushFilter() } lastFilterIndex = i + 1 } else { switch (c) { case 0x22: inDouble = true; break // " case 0x27: inSingle = true; break // case 0x5B: square++; break // [ case 0x5D: square--; break // ] case 0x7B: curly++; break // { case 0x7D: curly--; break // } default: break; } } } pushDir() return dirs } function pushDir () { dir.raw = str.slice(begin, i) if (dir.expression === undefined) {// ++ 這里也需要進行判斷,如果有值代表已經(jīng)被過濾器分支設(shè)置過了,這里就不需要設(shè)置 dir.expression = str.slice(argIndex, i).trim() } else {// ++ 添加過濾器 pushFilter() } dirs.push(dir) } function pushFilter() { var exp = str.slice(lastFilterIndex, i).trim() if (exp) { var tokens = exp.match(/[^\s"]+|[^]+|"[^"]+"/g) var filter = {} filter.name = tokens[0] filter.args = tokens.length > 1 ? tokens.slice(1) : null dir.filters = dir.filters || [] dir.filters.push(filter) } }

    把上面的代碼替換掉vue源碼里的相關(guān)代碼,測試了一下基本用例是能跑通的,但是可能還會有其他一些特殊場景沒有照顧到,更完善的代碼請自行閱讀vue源碼。

    掃描二維碼推送至手機訪問。

    版權(quán)聲明:本文由財神資訊-領(lǐng)先的體育資訊互動媒體轉(zhuǎn)載發(fā)布,如需刪除請聯(lián)系。

    本文鏈接:http://www.daniuzhishi.com/?id=44542

    “Vue0.11版本源碼閱讀系列四:詳解指令值解析函數(shù)” 的相關(guān)文章

    2022世界杯 | 烏拉圭對陣韓國 還有頗多“重慶足球元素”

    2022世界杯 | 烏拉圭對陣韓國 還有頗多“重慶足球元素”

     /////////// 最新比賽結(jié)果 ///////////       瑞士   1 : 0   喀麥隆        &nbs...

    足球為什么是世界第一運動?有何魅力?

    足球為什么是世界第一運動?有何魅力?

    12.27,補一個視頻,天下足球2018的告別——維猜 天足拿去了我成年后所有的眼淚—————————————————————————— 1 有一個桑德蘭小球迷叫“布拉德利”,他在2013年被...

    中國足球“搶戲”世界杯

    中國足球“搶戲”世界杯

    北京時間11月22日晚,2022世界杯C組首輪,阿根廷迎戰(zhàn)沙特阿拉伯。最終,奪冠熱門阿根廷1-2不敵沙特阿拉伯,爆出本屆世界杯開賽以來第一大冷門。 北京時間11月23日晚,2022卡塔爾世界杯展開E組首輪爭奪,4屆世界...

    【競彩足球推薦】 001 西甲 巴倫西亞 VS 皇家貝蒂斯 002 英超 阿斯頓維拉 VS 利物浦?能否穩(wěn)定發(fā)揮?你看好哪一隊?

    【競彩足球推薦】 001 西甲 巴倫西亞 VS 皇家貝蒂斯 002 英超 阿斯頓維拉 VS 利物浦?能否穩(wěn)定發(fā)揮?你看好哪一隊?

    體彩公益,樂善人生 為國家公益事業(yè)添磚加瓦 從我做起 前言: 以下賽事解讀,僅代表個人看法。 風(fēng)水輪流轉(zhuǎn),競彩亞盤也是這般!選擇和勇氣同樣重要!合理投注,理性選擇,穩(wěn)步收金! ——小王 奧利給!昨日競彩足球推薦了001,00...

    足球——E組:日本不敵哥斯達(dá)黎加(2)

    足球——E組:日本不敵哥斯達(dá)黎加(2)

    當(dāng)日,在卡塔爾賴揚艾哈邁德·本·阿里體育場進行的2022卡塔爾世界杯足球賽E組比賽中,日本隊以0比1不敵哥斯達(dá)黎加隊。...

    ?