`
boyitech
  • 浏览: 86041 次
  • 性别: Icon_minigender_1
  • 来自: 南通
社区版块
存档分类
最新评论

博弈AngularJS讲义(15) - HTML Compiler

阅读更多

  Angular HTML编译器可以让开发者通过定制标签或者属性来拓展HTML语法。通过Angular HTML编译器,我们可以给任何HTML元素及其属性赋予额外的行为,丰富HTML的语义。Angular把这种行为扩展称作指令。

  HTML使用了声明式的语法,例如我们只需在任何HTML元素上加上 align="center"属性即可让浏览器对元素进行居中对齐,而不用进行额外的编程来实现居中对齐。然而这种声明式的语言是有局限性的,HTML的语法集是有限的,浏览器引擎无法识别更多的语法。例如我们无法在HTML语法中声明让文本在离左侧1/3处对齐。

  Angular框架提供了一些指令集丰富了HTML语义,方便我们构建应用。同时Angular还提供了一套机制让开发者自定义指令。在Angular应用启动阶段,HTML编译器会“编译”指令,这个过程发生在浏览器端,无需与服务端交互。

 

Angular编译器

  编译器是Angular框架的一个服务组件,$compiler会遍历DOM树识别并处理指令,处理包含如下两个步骤:

  1. 编译(compile): 遍历DOM树,识别收集指令,作为连接函数的输入。

  2. 连接(linking):将指令绑定到作用域并生成动态的视图,即双向数据绑定。模型数据的变化会触发视图的更新,反之,用户与视图交互也会导致模型数据的更新。

  一些指令会对集合类的模型做特殊的处理,例如ng-repeat会给集合中的每一项克隆同样的DOM元素,并创建子作用域。

 

指令

  指令即AngularJS HTML编译过程中遇到特殊的HTML标记或者属性时触发的行为。指令可以在HTML标签,属性,CSS类名以及注释中。例如下面的ng-bind指令:  

 

<span ng-bind="exp"></span>
<span class="ng-bind: exp;"></span>
<ng-bind></ng-bind>
<!-- directive: ng-bind exp -->
  再看下面的例子,我们定义了一个draggable指令,赋予相应的元素可拖拽的行为。

 

  

angular.module('drag', []).
directive('draggable', function($document) {
  return function(scope, element, attr) {
    var startX = 0, startY = 0, x = 0, y = 0;
    element.css({
     position: 'relative',
     border: '1px solid red',
     backgroundColor: 'lightgrey',
     cursor: 'pointer',
     display: 'block',
     width: '65px'
    });
    element.on('mousedown', function(event) {
      // Prevent default dragging of selected content
      event.preventDefault();
      startX = event.screenX - x;
      startY = event.screenY - y;
      $document.on('mousemove', mousemove);
      $document.on('mouseup', mouseup);
    });

    function mousemove(event) {
      y = event.screenY - startY;
      x = event.screenX - startX;
      element.css({
        top: y + 'px',
        left:  x + 'px'
      });
    }

    function mouseup() {
      $document.off('mousemove', mousemove);
      $document.off('mouseup', mouseup);
    }
  };
});
    这里我们扩展了span标签,通过draggable属性赋予其可拖拽的行为:

 

 

<span draggable>Drag ME</span>
 

 

    运行结果:

   

 

理解视图

  大多数模板系统都是将基于字符串的静态模板上的片段用模型数据替换。原理如下图:  


 

  这种单向数据绑定意味着每次模型数据更新后需要重新通过innerHTML的方式将数据与模板绑定。

  Angular编译器处理基于DOM的模板,通过linking函数实现模板和模型的视图双向绑定。开发者无需添加任何代码手动更新视图。

 

     

指令的编译过程

   Angular操作的是DOM节点,而不是静态的字符模板。通常, 我们都不会注意到这个约束,因为在页面加载是,浏览器会自动将HTML解析成DOM。

  HTML编译可发生在如下三个阶段:

  1. $compile遍历DOM匹配识别指令。

   如过编译器发现HTML元素与指令匹配时,会将指令加入到与该DOM元素对应的指令集合里。也就是可以一个HTML元素可以有多个指令。

  2. 当编译器识别出元素的所有指令后, 编译器会对匹配的指令按优先级排序,每个指令的compile方法会被相继执行,在执行过程中可以修改DOM。每个compile都会返回一个link方法,Angular会将返回的的link函数合并成一个大的link过程。

 3. $compile服务组件会将模板与模型通过作用域连接起来, 通过调用指令的linking方法,在DOM元素上注册事件监听器并建立$watch相应的作用域。这样对作用域模型的更新将会即时更新到视图。下面关于$compile服务的代码将帮助我们更好的理解:

 

var $compile = ...; // injected into your code
var scope = ...;
var parent = ...; // DOM element where the compiled template can be appended

var html = '<div ng-bind="exp"></div>';

// Step 1: parse HTML into DOM element
var template = angular.element(html);

// Step 2: compile the template
var linkFn = $compile(template);

// Step 3: link the compiled template with the scope.
var element = linkFn(scope);

// Step 4: Append to DOM (optional)
parent.appendChild(element);
                                                                                                                                                                        编译与连接的区别                

 

   很少有指令有compile方法,因为大多数指令不会改变整个DOM元素的结构, 而是丰富元素的行为。指令通常都有link方法,来建立模型和作用域模型的双向同步机制。让我们看如下的例子:          

 

Hello {{user.name}}, you have these actions:
<ul>
  <li ng-repeat="action in user.actions">
    {{action.description}}
  </li>
</ul>
   Angular编译器将会识别出{{user.name}}和ng-repeat指令, ng-repeat需要迭代user.actions,给每个action克隆<li>元素, 当user.actions发生变化是情况将会变得更加复杂,为了提高克隆效率,需要将所有action共有的部分抽离出来,对于<li>需要一份干净的copy. 当新的action项添加进来时,会克隆一份<li>模板加入到<ul>中, 并为每个<li>创建独立的作用域。简单的做法是一次把<li>插入<ul>并进行编译,这样会导致很多重复的工作。 特别是每次都需要遍历li,频繁的操作会引发效率问题,使页面响应变慢。

 

  为了提搞效率Angular将编译过程分成两个阶段:

   - compile阶段识别出所有符合条件的指令,并按优先级排序。

   - link阶段建立视图与模型的双向绑定。

  

理解作用域的工作原理

  指令主要被用来构建可重用的组件。下面是一个简单的对话框的指令:

  

<div>
  <button ng-click="show=true">show</button>

  <dialog title="Hello {{username}}."
          visible="show"
          on-cancel="show = false"
          on-ok="show = false; doSomething()">
     Body goes here: {{username}} is {{title}}.
  </dialog>
</div>
   点击show按钮打开对话框,对话框含有标题与username绑定,还包含了一个消息体。下面是一个对话框模板的定义:

 

 

<div ng-show="visible">
  <h3>{{title}}</h3>
  <div class="body" ng-transclude></div>
  <div class="footer">
    <button ng-click="onOk()">Save changes</button>
    <button ng-click="onCancel()">Close</button>
  </div>
</div>

    只有将对话框与作用域绑定才会正确工作, 该作用域中必须定义title属性以及onOk和onCancel, 而我们希望的是dialog有自己的作用域,减少对外部的依赖,达到完全的可重用。 为解决作用域映射的问题,我们使用scope创建局部属性: 

   

transclude: true,
scope: {
    title: '@',             // the title uses the data-binding from the parent scope
    onOk: '&',              // create a delegate onOk function
    onCancel: '&',          // create a delegate onCancel function
    visible: '='            // set up visible to accept data-binding
},
restrict: 'E',
replace: true

 

 

  • 大小: 1.4 KB
  • 大小: 25.9 KB
  • 大小: 43.2 KB
分享到:
评论

相关推荐

    pg141-dds-compiler_Xilinx_pg141-dds_pg141-dds-compiler_

    标题中的“pg141-dds-compiler_Xilinx_pg141-dds_pg141-dds-compiler_”暗示了这是一个与Xilinx公司的DDS(Direct Digital Synthesis,直接数字频率合成)编译器相关的资源,版本号可能是14.1。DDS是一种广泛应用于...

    device-tree-compiler安装包以及依赖包

    device-tree-compiler_1.4.7-1_amd64.deb 安装包以及其依赖包。 在ubuntu 22.04上离线安装测试可行。推荐大家使用 总共hi三个包,分别是 libfdt1_1.4.7-1_amd64.deb libfdt-dev_1.4.7-1_amd64.deb device-tree-...

    commons-compiler-3.0.8-API文档-中文版.zip

    赠送jar包:commons-compiler-3.0.8.jar; 赠送原API文档:commons-compiler-3.0.8-javadoc.jar; 赠送源代码:commons-compiler-3.0.8-sources.jar; 赠送Maven依赖信息文件:commons-compiler-3.0.8.pom; 包含...

    device-tree-compiler_1.4.7-3ubuntu2_amd64.deb

    下载后ubuntu 终端安装命令:dpkg -i device-tree-compiler_1.4.7-3ubuntu2_amd64.deb 直接安装,外网下载太慢上传备用

    scala-compiler-2.11.8-API文档-中英对照版.zip

    赠送jar包:scala-compiler-2.11.8.jar; 赠送原API文档:scala-compiler-2.11.8-javadoc.jar; 赠送源代码:scala-compiler-2.11.8-sources.jar; 赠送Maven依赖信息文件:scala-compiler-2.11.8.pom; 包含翻译后...

    kotlin-compiler-embeddable-1.3.50.jar

    kotlin-compiler-embeddable-1.3.50.jar下载后直接可用(亲测)。Could not download kotlin-compiler-embeddable.jar,是墙的原因 没有下载下来kotlin-compiler-embeddable.jar的jar包资源。 把下载好的jar,放在...

    commons-compiler-3.1.4-API文档-中文版.zip

    赠送jar包:commons-compiler-3.1.4.jar; 赠送原API文档:commons-compiler-3.1.4-javadoc.jar; 赠送源代码:commons-compiler-3.1.4-sources.jar; 赠送Maven依赖信息文件:commons-compiler-3.1.4.pom; 包含...

    Android studio Kotlin kotlin-compiler-embeddable-1.6-M1.jar

    otlin-compiler-embeddable-1.6-M1 下载慢 otlin-compiler-embeddable 下载慢 直接复制到 C:\Users\xxx\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.6.0-M1

    CC-RL Compiler

    CC-RL Compiler用户手册 CC-RL Compiler是瑞萨电子公司(Renesas Electronics Corp.)推出的编译器,用于RL78家族单片机的开发。该编译器提供了一个强大的开发环境,帮助开发者快速、可靠地开发基于RL78单片机的...

    kotlin-compiler-embeddable 1.6.10

    《Kotlin-Compiler-Embeddable 1.6.10:Android开发中的编译器嵌入实践》 在移动应用开发领域,尤其是在Android平台上,Kotlin已经成为了开发者们广泛采用的语言。它以其简洁的语法、强大的功能以及与Java的无缝...

    commons-attributes-compiler-2.2.zip

    commons-attributes-compiler-2.2.zipcommons-attributes-compiler-2.2.zipcommons-attributes-compiler-2.2.zipcommons-attributes-compiler-2.2.zipcommons-attributes-compiler-2.2.zip

    device-tree-compiler_1.4.5-3_amd64.deb

    fdtput版本更新至1.4.5,下载device-tree-compiler_1.4.5-3_amd64.deb,dpkg -i安装

    maven-compiler-plugin-3.8.0-source-release插件

    `maven-compiler-plugin-3.8.0-source-release` 是 Maven 生态系统中不可或缺的一部分,它提供了可靠的源代码编译功能,使得开发者能够专注于编写代码,而无需关心构建过程的细节。通过理解 Maven 插件的工作原理和...

    kotlin-scripting-compiler-impl.jar

    kotlin-scripting-compiler-impl.jar

    kotlin-compiler-embeddable 1.7.20

    kotlin-compiler-embeddable 1.7.20

    kotlin-compiler-embeddable-1.4.10.jar

    文件:kotlin-compiler-embeddable-1.4.10.jar下载,kotlin开发必备

    plexus-compiler--2.8.4.jar.rar

    这个压缩包文件"plexus-compiler--2.8.4.jar.rar"包含了Plexus Compiler的三个关键模块,分别是plexus-compiler-api-2.8.4.jar、plexus-compiler-javac-2.8.4.jar和plexus-compiler-manager-2.8.4.jar,这些文件版本...

    commons-compiler-2.7.6-API文档-中文版.zip

    赠送jar包:commons-compiler-2.7.6.jar; 赠送原API文档:commons-compiler-2.7.6-javadoc.jar; 赠送源代码:commons-compiler-2.7.6-sources.jar; 赠送Maven依赖信息文件:commons-compiler-2.7.6.pom; 包含...

    maven-compiler-plugin-3.8.1.jar

    maven是个项目管理工具,如果我们不告诉它我们的代码要使用什么样的jdk版本编译的话,它就会用maven-compiler-plugin默认的jdk版本来进行处理,这样就容易出现版本不匹配,以至于可能导致编译不通过的问题。...

Global site tag (gtag.js) - Google Analytics