AngularJS HTML编译器介绍


Posted in Javascript onDecember 06, 2014

概览

AngularJS的HTML编译器能让浏览器识别新的HTML语法。它能让你将行为关联到HTML元素或者属性上,甚至能让你创造具有自定义行为的新元素。AngularJS称这种行为扩展为“指令”

HTML在编写静态页面时,有很多声明式的结构来控制格式。比如你要把某个内容居中,你不必告诉浏览器“去找到窗口的中点位置,然后跟内容的中间结合”。你只需要添加一个 align="center" 的属性给需要内容居中的元素就行了。这就是声明式语言的强大之处。

但是声明式语言也有力所不能及的地方,原因之一在于你不能用它来让浏览器识别新的语法。比如说,你不要内容居中,而是居左到1/3,这时它就做不到了。所以我们需要一个办法让浏览器能学会新的HTML语法。

AngularJS生来自带一些对创建APP非常有用的指令。我们也希望你能自己创造一些对你自己的应用有用的指令。这些扩展的指令就是你创建APP的 “特定领域语言(Domain Specific Language)”。

编译的过程都会在浏览器端发生;服务器端不会参与到其中的任何步骤,也不会做预编译。

编译器(complier)

编译器是AngularJS提供的一项服务,它通过遍历DOM来查找和它相关的属性。整个编译的过程分为两个阶段。

1.编译: 遍历DOM并且收集所有的相关指令,生成一个链接函数。

2.链接: 给指令绑定一个作用域,生成一个动态的视图。作用域模型的任何改变都会反映到视图上,并且视图上的任何用户操作也都会反映到作用域模型。这使得作用域模型成为你的业务逻辑里唯一要关心的东西。

有一些指令,比如ng-repeat会为数据集合里的每一项DOM元素都克隆一次。将整个编译过程分为编译和链接两个阶段的作法改善了整体的性能,因为克隆出来的模板总共只需要被编译一次,然后链接到各自的模型实例上就行了。

指令

指令指示的是“当关联的HTML结构进入编译阶段时应该执行的操作”。指令可以写在元素的名称里,属性里,css类名里,注释里。下面有几个功能相同的使用ng-bind指令的例子。

<span ng-bind="exp"></span>

<span class="ng-bind: exp;"></span>

<ng-bind></ng-bind>

<!-- directive: ng-bind exp -->

指令本质上只是一个当编译器编译到相关DOM时需要执行的函数。你可以在指令API文档中找到更详尽的关于指令的资料。

下面是一条能让元素变得可拖拽的指令。注意<span>元素里的那个draggable属性。

index.html:

<!doctype html>

<html ng-app="drag">

  <head>

    <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>

    <script src="script.js"></script>

  </head>

  <body>

    <span draggable>Drag ME</span>

  </body>

</html>

script.js:

angular.module('drag', []).

directive('draggable', function($document) {

    var startX=0, startY=0, x = 0, y = 0;

    return function(scope, element, attr) {

      element.css({

       position: 'relative',

       border: '1px solid red',

       backgroundColor: 'lightgrey',

       cursor: 'pointer'

      });

      element.bind('mousedown', function(event) {

        startX = event.screenX - x;

        startY = event.screenY - y;

        $document.bind('mousemove', mousemove);

        $document.bind('mouseup', mouseup);

      });
      function mousemove(event) {

        y = event.screenY - startY;

        x = event.screenX - startX;

        element.css({

          top: y + 'px',

          left:  x + 'px'

        });

      }
      function mouseup() {

        $document.unbind('mousemove', mousemove);

        $document.unbind('mouseup', mouseup);

      }

    }

 });

通过加入draggable属性可以让任何HTML元素都实现这个新的行为。我们这种改进的优美之处在于我们给了浏览器新能力。我们用了一种只要开发者熟悉HTML规则,就会举得很自然的方式扩展了浏览器理解新行为新语法的能力。

理解视图

网上有很多的模板系统。他们大多数都是“将静态的字符模板和数据绑定,生成新字符,然后通过innerHTML插入到页面元素中”。

这意味着数据上的任何改变,都会导致数据要重新和模板结合生成新字符,再插入到DOM里。这其中会出现的问题有:需要读取用户输入并和模型的数据结合,需要覆写用户的输入,需要手动管理整个更新过程,缺少丰富的表现形式。

AngularJS则不同,AngularJS编译器使用的是带指令的DOM,而不是字符串模板。它返回的是一个链接函数,这个函数和作用域模型结合就会生成一个动态视图。这个视图和模型的绑定过程是“透明的”。开发者不需要做任何关于更新视图的工作。并且应用没有用到innerHTML,所以我们也不用覆写用户的输入。更特别的是,Angular的指令不仅仅能使用字符串形式的绑定,还可以使用一些指示行为的结构体。

AngularJS的编译会生成一个“稳定的DOM”。这意味绑定了数据模型的DOM元素的实例不会在绑定的生命周期中发生改变。这也意味着代码中可以获取到DOM元素的实例引用并注册事件,不用担心这用引用会在模板和数据的结合时丢失。

Javascript 相关文章推荐
js验证表单第二部分
Nov 25 Javascript
JS 参数传递的实际应用代码分析
Sep 13 Javascript
事件模型在各浏览器中存在差异
Oct 20 Javascript
Dom 结点创建 基础知识
Oct 01 Javascript
js下拉框二级关联菜单效果代码具体实现
Aug 03 Javascript
javascript实现行拖动的方法
May 27 Javascript
基于Bootstrap实现tab标签切换效果
Apr 15 Javascript
jQuery EasyUI结合zTree树形结构制作web页面
Sep 01 jQuery
json2.js 入门教程之使用方法与实例分析
Sep 14 Javascript
在微信小程序中保存网络图片
Feb 12 Javascript
layui下拉框获取下拉值(select)的例子
Sep 10 Javascript
使用 Vue-TCB 快速在 Vue 应用中接入云开发的方法
Feb 10 Javascript
AngularJS初始化过程分析(引导程序)
Dec 06 #Javascript
什么是 AngularJS?AngularJS简介
Dec 06 #Javascript
AngularJS入门教程(二):AngularJS模板
Dec 06 #Javascript
AngularJS入门教程(一):静态模板
Dec 06 #Javascript
AngularJS入门教程(零):引导程序
Dec 06 #Javascript
AngularJS入门教程之学习环境搭建
Dec 06 #Javascript
AngularJS入门教程之Hello World!
Dec 06 #Javascript
You might like
PHP 数据结构 算法 三元组 Triplet
2011/07/02 PHP
PHP spl_autoload_register实现自动加载研究
2011/12/06 PHP
php实现的证件照换底色功能示例【人像抠图/换背景图】
2020/05/29 PHP
用jQuery扩展自写的 UI导航
2010/01/13 Javascript
niceTitle 基于jquery的超链接提示插件
2010/05/31 Javascript
让JavaScript拥有类似Lambda表达式编程能力的方法
2010/09/12 Javascript
读jQuery之八 包装事件对象
2011/06/21 Javascript
使用JavaScript 实现各种跨域的方法
2013/05/08 Javascript
再次谈论React.js实现原生js拖拽效果引起的一系列问题
2016/04/03 Javascript
基于css3新属性transform及原生js实现鼠标拖动3d立方体旋转
2016/06/12 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
Vue2.0 组件传值通讯的示例代码
2017/08/01 Javascript
node.js 模块和其下载资源的镜像设置的方法
2018/09/06 Javascript
vue实现在v-html的html字符串中绑定事件
2019/10/28 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
Vue实现浏览器打印功能的代码
2020/04/17 Javascript
vue-cli单页面预渲染seo-prerender-spa-plugin操作
2020/08/10 Javascript
JavaScript实现前端倒计时效果
2021/02/09 Javascript
[02:16]2018年度CS GO最具人气选手-完美盛典
2018/12/16 DOTA
[42:06]2019国际邀请赛全明星赛 8.23
2019/09/05 DOTA
python实现支持目录FTP上传下载文件的方法
2015/06/03 Python
利用Python-iGraph如何绘制贴吧/微博的好友关系图详解
2017/11/02 Python
python生成随机图形验证码详解
2017/11/08 Python
python自动结束mysql慢查询会话的实例代码
2019/10/27 Python
python反转列表的三种方式解析
2019/11/08 Python
澳大利亚相机之家:Camera House
2017/11/30 全球购物
说出数据连接池的工作机制是什么?
2013/04/19 面试题
数控专业大学生的自我鉴定
2013/11/13 职场文书
护士求职自荐信范文
2014/03/19 职场文书
《中国梦我的梦》小学生演讲稿
2014/08/20 职场文书
2014年纪委工作总结
2014/12/05 职场文书
试用期旷工辞退通知书
2015/04/17 职场文书
2019最新校园运动会广播稿!
2019/06/28 职场文书
“爱眼护眼,提前预防近视”倡议书3篇
2019/10/30 职场文书
MySQL数据库之内置函数和自定义函数 function
2022/06/16 MySQL
新的CSS 伪类函数 :is() 和 :where()示例详解
2022/08/05 HTML / CSS