日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

html 属于mvvm框架,前端MVVM框架avalon揭秘 - HTML编译器

發布時間:2024/9/27 HTML 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html 属于mvvm框架,前端MVVM框架avalon揭秘 - HTML编译器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MVVM試圖更加清晰的講用戶界面(UI)開發從應用程序的業務邏輯與行為中心分離,由于,不少這樣的模式的實現都須要利用聲明式數據綁定來實現講View(視圖)工做從其余層分離css

因此出現了一大堆自定義的聲明式的語法:html

如:Avalonnode

顧名思義,自定義聲明語法,那么游覽器自己是不能識別的,那么如何游覽器能過識別自定義的HTML語法,它能讓你講行為關系到HTML元素或者屬性上,甚至能讓你創造具備自定義行為的新元素呢,咱們暫且講這個過程稱之為“HTML編譯”吧。數組

咱們先看一段HTML代碼瀏覽器

{{ w }} x {{ h }}

W:

H:

avalon.define("box", function(vm) {

vm.w = 100;

vm.h = 100;

vm.click = function() {

vm.w = parseFloat(vm.w) + 10;

vm.h = parseFloat(vm.h) + 10;

}

})

avalon.scan(document.getElementById('box'));

HTML結構中充斥了大量的ms開頭的自定義標簽,還有{}插值表達式。。等等ruby

聲明1:

ms-controller="box"

avalon提供ms-controller, ms-important來指定VM在視圖的做用范圍。好比有兩個VM,它們都有一個firstName屬性,在DIV中,若是咱們用 ms-controller="VM1", 那么對于DIV里面的{{firstName}}就會解析成VM1的firstName中的值。app

聲明2:

ms-css-width="w" ms-css-height="h"

用來處理樣式框架

聲明3:

ms-click="click"

avalon經過ms-on-click或ms-click進行事件綁定,并在IE對事件對象進行修復,并統一了全部瀏覽器對return false的處理dom

其實就是把部分的行為操做提高到了dom上了,而后有框架在后臺給你處理好,經過加入各類自定義的屬性可讓任何的HTML元素都實現這樣的行為函數

具體看源碼的執行流程:

總的來講就是匹配每一給節點上的屬性,經過匹配分配到指定的bindingHandlers處理函數上,以后的處理本章不暫時不涉及

//掃描入口

avalon.scan = function(elem, vmodel)

//掃描子節點

function scanNodes(parent, vmodels, callback)

//開始掃描

function scanTag(elem, vmodels)

//掃描文本

function scanText(textNode, vmodels)

//掃描表達式

function scanExpr(str)

//掃描屬性節點

function scanAttr(el, vmodels)

//抽取綁定

function executeBindings(bindings, vmodels)

//抽取文本綁定

function extractTextBindings(textNode)

看看命名就大概能猜出函數的做用了

1.入口函數? avalon.scan

avalon.scanavalon.scan = function(elem, vmodel) {

elem = elem || root

var vmodels = vmodel ? [].concat(vmodel) : []

scanTag(elem, vmodels)

}

默認從文本的根documentElement開始,若是傳遞了第一個elem,那么就是指定了掃描的做用域了,相似 jQuery( selector, [ context ] )

2. 執行掃描 scanTag

avalon.scanvmodels = vmodels || []

var a = elem.getAttribute(prefix + "skip")

var b = elem.getAttribute(prefix + "important")

var c = elem.getAttribute(prefix + "controller")

//這三個綁定優先處理,其中a > b > c

if (typeof a === "string") {

return

} else if (b) {

if (!VMODELS[b]) {

return

} else {

vmodels = [VMODELS[b]]

elem.removeAttribute(prefix + "important")

}

} else if (c) {

var newVmodel = VMODELS[c]

if (!newVmodel) {

return

}

vmodels = [newVmodel].concat(vmodels)

elem.removeAttribute(prefix + "controller")

}

scanAttr(elem, vmodels) //掃描特性節點

if (!stopScan[elem.tagName.toLowerCase()] && rbind.test(elem.innerHTML)) {

scanNodes(elem, vmodels)

}

依次要檢測是當前元素上是否有ms-skip,ms-important,ms-controller屬性,用于最開始的處理

若是ms-controller存在就取出vm視圖模型對象

清除這個自定義屬性

執行sacnAttr 屬性掃描

3. 掃描屬性節點 scanAttr

avalon.scanfunction scanAttr(el, vmodels) {

var bindings = []

for (var i = 0, attr; attr = el.attributes[i++]; ) { 1

if (attr.specified) { 2

var isBinding = false

if (attr.name.indexOf(prefix) !== -1) { 3

//若是是以指定前綴命名的

var type = attr.name.replace(prefix, "")

if (type.indexOf("-") > 0) { 4

var args = type.split("-")

type = args.shift()

}

isBinding = typeof bindingHandlers[type] === "function" 5

}

if (isBinding) {

bindings.push({ 6

type: type,

args: args || [],

element: el,

remove: true,

node: attr,

value: attr.nodeValue

})

}

}

}

executeBindings(bindings, vmodels)

}

attributes 屬性返回包含被選節點屬性的 NamedNodeMap。

若是在文檔中設置了屬性值,則 specified 屬性返回 true.

是不是avalon的HTML指示 "ms-"開頭

若是還指定了參數

能找到對應的處理函數

bindings 保存參數

4. 執行綁定 executeBindings

avalon.scanfunction executeBindings(bindings, vmodels) {

bindings.forEach(function(data) {

var flag = bindingHandlers[data.type](data, vmodels)

if (flag !== false && data.remove) { //移除數據綁定,防止被二次解析

data.element.removeAttribute(data.node.name)

}

})

}

找到對應的類型的bindingHandlers方法,傳入數據與vm對象,實現處理

移除數據綁定,防止被二次解析

5. 掃描子節點 scanNodes

avalon.scanfunction scanNodes(parent, vmodels, callback) {

var nodes = aslice.call(parent.childNodes);

callback && callback();

for (var i = 0, node; node = nodes[i++]; ) {

if (node.nodeType === 1) {

scanTag(node, vmodels) //掃描元素節點

} else if (node.nodeType === 3) {

scanText(node, vmodels) //掃描文本節點

}

}

}

其實就循環處理子節點列表了,注意要過濾空文本類型

若是是元素節點就遞歸循環scanTag方法

若是是文本節點就scanText

6. 掃描文本 scanText

avalon.scanfunction scanText(textNode, vmodels) {

var bindings = extractTextBindings(textNode)

if (bindings.length) {

executeBindings(bindings, vmodels)

}

}

7.抽出文本綁定 extractTextBindings

avalon.scanfunction extractTextBindings(textNode) {

var bindings = [],

tokens = scanExpr(textNode.nodeValue)//分解表達式

if (tokens.length) {

while (tokens.length) { //將文本轉換為文本節點,并替換原來的文本節點

var token = tokens.shift()

var node = DOC.createTextNode(token.value)

if (token.expr) { //若是分解的是表達式

var filters = token.filters

var binding = {

type: "text",

node: node,

args: [],

element: textNode.parentNode,

value: token.value,

filters: filters

}

if (filters && filters.indexOf("html") !== -1) {

avalon.Array.remove(filters, "html")

binding.type = "html"

binding.replaceNodes = [node]

}

bindings.push(binding) //收集帶有插值表達式的文本

}

documentFragment.appendChild(node)

}

textNode.parentNode.replaceChild(documentFragment, textNode)

}

return bindings

}

文本解析是個比較復雜的東西,能夠匹配不少種狀況,因此須要加入不少解析的規則

scanExpr 就是掃描的表達式的匹配

documentFragment 先把這個結構讓到文檔碎片中,性能處理

8. 表達式匹配scanExpr

avalon.scanfunction scanExpr(str) {

var tokens = [],

value, start = 0,

stop

if (rexpr.test(str)) {

do {

var stop = str.indexOf(openTag, start)

if (stop === -1) {

break

}

value = str.slice(start, stop)

if (value) { // {{ 左邊的文本

tokens.push({

value: value,

expr: false

})

}

start = stop + openTag.length

stop = str.indexOf(closeTag, start)

if (stop === -1) {

break

}

value = str.slice(start, stop)

if (value) { //{{ }} 之間的表達式

var leach = []

if (value.indexOf("|") > 0) { // 注意排除短路與

value = value.replace(rfilters, function(c, d, e) {

leach.push(d + (e || ""))

return c.charAt(0)

})

}

tokens.push({

value: value,

expr: true,

filters: leach.length ? leach : void 0

})

}

start = stop + closeTag.length;

} while (1);

value = str.slice(start);

if (value) { //}} 右邊的文本

tokens.push({

value: value,

expr: false

})

}

}

return tokens

}

代碼很長,可是處理的東西確很簡單的

好比:

"{{ w }} x {{ h }}" 一個插值表達式,那么應該如何解析

分析這個表達式,解析能夠分三塊

1.? {{ w }}

2??? x

3?? {{ h }}

左右兩邊都是vm視圖全部關聯的屬性,中間x就是求值

那么解析的規則,分解3個部分,組成處理數據

tokens 就有3個組成對象

expr: true

filters: undefined

value: " w "

expr: false

value: " x "

expr: true

filters: undefined

value: " h "

解析后分解成綁定的數據

而后就是一次循環了, 遇到條件stopScan就終止了

因此總結scan無非就干了一件事,掃描到指定的行為,發送數據給處理函數

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的html 属于mvvm框架,前端MVVM框架avalon揭秘 - HTML编译器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。