前端MVVM框架avalon揭秘 - HTML编译器

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:

MVVM试图更加清晰的讲用户界面(UI)开发从应用程序的业务逻辑与行为中心分离,因为,很多这样的模式的实现都需要利用声明式数据绑定来实现讲View(视图)工作从其他层分离

所以出现了一大堆自定义的声明式的语法:

如:Avalon

  1. 作用域绑定(ms-controller, ms-important)
  2. 模板绑定(ms-include)
  3. 数据填充(ms-text, ms-html)
  4. 类名切换(ms-class, ms-hover, ms-active)
  5. 事件绑定(ms-on,……)
  6. 显示绑定(ms-visible)
  7. 插入绑定(ms-if)
  8. 双工绑定(ms-duplex,原来的ms-model)
  9. 样式绑定(ms-css)
  10. 数据绑定(ms-data)
  11. 布尔属性绑定(ms-checked, ms-selected, ms-readonly, ms-disabled, ms-enabled)
  12. 字符串属性绑定(ms-title, ms-src, ms-href……)
  13. 万能属性绑定(ms-attr)
  14. 万能绑定(ms-bind)
  15. 数组循环绑定(ms-each)
  16. 对象循环绑定(ms-with)
    等等………

顾名思义,自定义声明语法,那么游览器本身是不能识别的,那么如何游览器能过识别自定义的HTML语法,它能让你讲行为关系到HTML元素或者属性上,甚至能让你创造具有自定义行为的新元素呢,我们暂且讲这个过程称之为“HTML编译”吧。

我们先看一段HTML代码

2
3
4
5
6
7
8
9
10
<div id= 'box'  ms-controller= "box" >
 
     <div style= " background: #a9ea00;"  ms-css-width= "w"  ms-css-height= "h"   ms-click= "click" ></div>
 
     <p>{{ w }} x {{ h }}</p>
     <p>W: <input type= "text"  ms-model= "w"  data-event= "change" /></p>
     <p>H: <input type= "text"  ms-model= "h"  /></p>
 
</div>
2
3
4
5
6
7
8
9
10
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开头的自定义标签,还有{}插值表达式。。等等

声明1:

2
ms-controller= "box"

avalon提供ms-controller, ms-important来指定VM在视图的作用范围。比如有两个VM,它们都有一个firstName属性,在DIV中,如果我们用 ms-controller="VM1", 那么对于DIV里面的{{firstName}}就会解析成VM1的firstName中的值。

声明2:

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

用来处理样式

声明3:

2
ms-click= "click"

avalon通过ms-on-click或ms-click进行事件绑定,并在IE对事件对象进行修复,并统一了所有浏览器对return false的处理

 

其实就是把部分的行为操作提升到了dom上了,然后有框架在后台给你处理好,通过加入各种自定义的属性可以让任何的HTML元素都实现这样的行为

 

具体看源码的执行流程:

总的来说就是匹配每一给节点上的属性,通过匹配分配到指定的bindingHandlers处理函数上,之后的处理本章不暂时不涉及

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//扫描入口
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.scan

默认从文本的根documentElement开始,如果传递了第一个elem,那么就是指定了扫描的作用域了,类似 jQuery( selector, [ context ] )

 

2. 执行扫描 scanTag

avalon.scan
  • 依次要检测是当前元素上是否有ms-skip,ms-important,ms-controller属性,用于最开始的处理
  • 如果ms-controller存在就取出vm视图模型对象
  • 清除这个自定义属性
  • 执行sacnAttr 属性扫描

 

3. 扫描属性节点 scanAttr

avalon.scan

attributes 属性返回包含被选节点属性的 NamedNodeMap。

如果在文档中设置了属性值,则 specified 属性返回 true.

是否是avalon的HTML指示 "ms-"开头

如果还指定了参数

能找到对应的处理函数

bindings 保存参数

 

4. 执行绑定 executeBindings

avalon.scan

找到对应的类型的bindingHandlers方法,传入数据与vm对象,实现处理

移除数据绑定,防止被二次解析

 

5. 扫描子节点 scanNodes

avalon.scan

其实就循环处理子节点列表了,注意要过滤空文本类型

如果是元素节点就递归循环scanTag方法

如果是文本节点就scanText

 

6. 扫描文本 scanText

avalon.scan

 

7.抽出文本绑定 extractTextBindings

avalon.scan

文本解析是个比较复杂的东西,可以匹配很多种情况,所以需要加入很多解析的规则

scanExpr 就是扫描的表达式的匹配

documentFragment 先把这个结构让到文档碎片中,性能处理

 

8. 表达式匹配scanExpr

avalon.scan

代码很长,但是处理的东西确很简单的

比如:

"{{ w }} x {{ h }}" 一个插值表达式,那么应该如何解析

分析这个表达式,解析可以分三块
1.  {{ w }} 

2    x 

3   {{ h }}

左右两边都是vm视图所有关联的属性,中间x就是求值

那么解析的规则,分解3个部分,组成处理数据

tokens 就有3个组成对象

  1. expr: true
  2. filters: undefined
  3. value: " w "
  1. expr: false
  2. value: " x "
  1. expr: true
  2. filters: undefined
  3. value: " h "

解析后分解成绑定的数据

 

然后就是一次循环了, 遇到条件stopScan就终止了

 

所以总结scan无非就干了一件事,扫描到指定的行为,发送数据给处理函数

 

本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3228457.html,如需转载请自行联系原作者
相关文章
|
1月前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
68 9
|
15天前
|
前端开发 JavaScript 搜索推荐
HTML与CSS在Web组件化中的核心作用及前端技术趋势
本文探讨了HTML与CSS在Web组件化中的核心作用及前端技术趋势。从结构定义、语义化到样式封装与布局控制,两者不仅提升了代码复用率和可维护性,还通过响应式设计、动态样式等技术增强了用户体验。面对兼容性、代码复杂度等挑战,文章提出了相应的解决策略,强调了持续创新的重要性,旨在构建高效、灵活的Web应用。
27 6
HTML 框架2
iframe标签用于在当前页面中嵌入另一个HTML页面。通过设置frameborder属性为&quot;0&quot;,可以移除iframe边框。iframe的src属性用于指定要嵌入的页面URL。例如,使用`&lt;iframe src=&quot;https://www.runoob.com&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;`可以无边框地显示RUNOOB.COM页面。
|
26天前
|
前端开发 JavaScript API
前端界的秘密武器:掌握这些框架,让你轻松秒杀99%的同行!
前端开发日新月异,掌握几个明星框架如React、Vue.js和Angular,不仅能让工作更得心应手,还能轻松超越同行。React以高效的虚拟DOM和组件化著称;Vue.js简洁易懂,灵活性高;Angular提供全面的解决方案,适合大型应用。此外,轻量级的Svelte也值得关注,其编译时处理设计提升了应用性能。掌握这些框架,结合深刻理解和灵活运用,助你在前端领域脱颖而出。
30 9
HTML 框架1
HTML框架允许在同一个浏览器窗口中同时显示多个页面。`&lt;iframe&gt;`标签用于嵌入其他网页,基本语法为 `&lt;iframe src=&quot;URL&quot;&gt;&lt;/iframe&gt;`。可以通过设置 `height` 和 `width` 属性来调整 iframe 的大小,例如:`&lt;iframe src=&quot;demo_iframe.htm&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&lt;/iframe&gt;`。属性值可以是像素或百分比。
|
2月前
|
JavaScript 前端开发 测试技术
前端全栈之路Deno篇(五):如何快速创建 WebSocket 服务端应用 + 客户端应用 - 可能是2025最佳的Websocket全栈实时应用框架
本文介绍了如何使用Deno 2.0快速构建WebSocket全栈应用,包括服务端和客户端的创建。通过一个简单的代码示例,展示了Deno在WebSocket实现中的便捷与强大,无需额外依赖,即可轻松搭建具备基本功能的WebSocket应用。Deno 2.0被认为是最佳的WebSocket全栈应用JS运行时,适合全栈开发者学习和使用。
123 7
|
2月前
|
缓存 前端开发 JavaScript
前端serverless探索之组件单独部署时,利用rxjs实现业务状态与vue-react-angular等框架的响应式状态映射
本文深入探讨了如何将RxJS与Vue、React、Angular三大前端框架进行集成,通过抽象出辅助方法`useRx`和`pushPipe`,实现跨框架的状态管理。具体介绍了各框架的响应式机制,展示了如何将RxJS的Observable对象转化为框架的响应式数据,并通过示例代码演示了使用方法。此外,还讨论了全局状态源与WebComponent的部署优化,以及一些实践中的改进点。这些方法不仅简化了异步编程,还提升了代码的可读性和可维护性。
|
2月前
|
前端开发 JavaScript 中间件
前端全栈之路Deno篇(四):Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
Deno 是由 Node.js 创始人 Ryan Dahl 开发的新一代 JavaScript 和 TypeScript 运行时,旨在解决 Node.js 的设计缺陷,具备更强的安全性和内置的 TypeScript 支持。本文介绍了如何使用 Deno 内置的 `Deno.serve` 快速创建 HTTP 服务,并详细讲解了 Oak 框架的安装和使用方法,包括中间件、路由和静态文件服务等功能。Deno 和 Oak 的结合使得创建 RESTful API 变得高效且简便,非常适合快速开发和部署现代 Web 应用程序。
105 2
HTML 框架3
iframe 是一种在网页中嵌入另一个 HTML 页面的技术。通过设置 iframe 的属性,可以显示指定的目标链接页面。例如,可以使用 iframe 嵌入 RUNOOB.COM 网站。HTML 中的 `&lt;iframe&gt;` 标签用于定义内联框架。
|
2月前
|
前端开发 JavaScript API
前端的全栈之路Meteor篇(完):关于前后端分离及与各框架的对比,浅析分离之下的潜在耦合
本文探讨了Meteor.js这一全栈JavaScript框架的特点与优势,特别是在前后端分离架构中的应用。Meteor通过共享数据结构和简化全栈开发流程,实现了前后端的紧密协作。文章还对比了其他全栈框架,如Next.js、Nuxt.js等,分析了各自的优势与适用场景,最后讨论了通过定义文档归属者和用户专有数据集简化后端构建及端云数据同步的方法。