$compile

这是个编译服务。编译一段HTML字符串或者DOM的模板, 产生一个将scope和模板连接到一起的函数。

编译服务主要是为指令编译DOM元素,下面的一大段也是主要介绍指令的。

下面是一个被声明的带指令定义对象的指令的示例:

  var myModule = angular.module(...);
myModule.directive('directiveName', [“injectables”,…,function factory(injectables,…) {
var directiveDefinitionObject = {
   priority: 0,
   template: '<div></div>', // or // function(tElement, tAttrs) { ... },
   // or
   // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
   replace: false,
   transclude: false,
   restrict: 'A',
   scope: false,
   controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
   controllerAs: 'stringAlias',
   require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
   compile: function compile(tElement, tAttrs, transclude) {
   return {
      pre: function preLink(scope, iElement, iAttrs, controller) { ... },
      post: function postLink(scope, iElement, iAttrs, controller) { ... }
     }
   // or
   // return function postLink( ... ) { ... }
   },
   // or
   // link: {
     // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
     // post: function postLink(scope, iElement, iAttrs, controller) { ... }
   // }
   // or
   // link: function postLink( ... ) { ... }
   };
   return directiveDefinitionObject;
});

这是一个完整的指令,所返回的对象的各项属性都写在上面了,下面对于指令对象属性的介绍,就不一一的写示例代码了,后面主要写下简单的就ok。

备注:任何为指定的参数都将设置为默认值。下面将会列出各默认值。

指令定义对象

指令定义的对象为编译器提供说明,其属性是:

priority
当有一个DOM元素中定义了多个指令,有时有必要指定的指令的应用顺序。在编译函数被调用之前,先将其按优先级排序。这个属性的值越大,优先级越高,将会更先被编译。具有相同优先级的指令的顺序是未定义的。默认优先级为0。

如果该属性设置为true,那么当前指令的优先将会放在最后一组将执行(在当前优先级的任何指令将仍然作为未定义优先级的设置执行)

scope

如果设置为false,则不会为指令创建任何scope。指令使用其父级scope。

如果设置为true,那么该指令将会创建一个新的子scope,这个scope继承父级的属性。如果在一个DOM的多个指令上定义新作用域,也只能创建一个新的作用域。模板有了新的作用域后,该作用域的规则不适用与模板所在的根节点。

如果设置为{},那么将会创建一个新的、隔离的作用域。该作用域不继承其父作用域,这样就不会在创建可重用的指令是影响到父作用域的数据。

这个隔离的作用域会有一组来自父作用域的数据组成的对象,该对象名称前缀为:

@
or @attr : 结合局部作用域属性的DOM元素上的属性值。在DOM元素上和指令scope中以string类型绑定。如果没指定名称,那么与假定的指令作用域中的名称相同。

=
or =attr:在指令作用域和父作用域之间设置数据的双向绑定。如果没指定名称,那么与假定的指令作用域中的名称相同。

&
or &attr:提供了在父作用域的上下文中执行的表达式。

controller

该指令的控制器构造函数。控制器将会在预编译之前被实例化,并且可与其他指令共享(参见require属性)。这实现了指令之间的通信,增强了相互之间的行为。可写入以下参数:

$scope:与元素相关联的当前作用域。

$element:当前元素。

$attr:当前元素上的属性。

$transclude:一个被预绑定到正确的嵌入范围的linking函数。该范围可以通过一个第一个可选的参数重写。function([scope], cloneLinkingFn).

require

需要另外一个指令并将其控制器作为第四个参数注入linking函数。需要以指令的字符串名称(或字符串数组)注入。如果使用了数组,注入的参数将是一个数组中的相应的顺序。如果没有找到这样的指令,或如果该指令没有控制器,那么将会出现一个错误。该属性名称前缀为:

无前缀:定位当前元素所需的控制器。如果未找到错误,抛出一个错误。

?:试图找到所需的控制器,如果没有找到,则通过空函数。

^:通过搜索元素的父节点来寻找所需的控制器,如果没找到,抛出个错误。

?^:通过搜索元素的父节点来寻找所需的控制器,如果没有找到,则通过空函数。

controllerAs

指令作用域内的控制器的别名。控制器的别名,以便在该指令模板中引用。该指令需要在适用范围内定义此配置。当指令被用作组件的情况下有用。

restrict

EACM的子集,限制了对一个特定的指令声明式的指令。

E:元素名称,<my-directive></my-directive>

A:元素属性,<div my-directive="exp"></div>

C:元素类:<div class="my-directive:
exp;"></div>

M:注释,<!--
directive: my-directive exp -->

template

将HTML的内容的指令块替换当前元素。过程将在新元素上更新之前旧元素的所有属性/类。该属性可以指定模板作为一个字符串或一个函数模板,采用两个参数tElement和tAttrs,并返回一个表示模板的字符串值。

templateUrl

与template基本相同,但模板通过指定的url加载。因为模板是异步加载的,所以conplie和link都会被赞同,等待模板加载完。

replace

指定要插入模块的位置,默认为false。

true:模板将会替换当前元素。

false:模板将会替换当前元素的内容。

transclude

编译元素的内容并且使其在指令内有效。这使得组件有私人的状态,并且嵌入的部分包含到父作用域。

true:该指令可嵌入内容。

false:嵌入整个单元包括在较低的优先级定义的任何指令。

compile

function compile(tElement, tAttrs,
transclude) { ... }

compile函数分配模板的转换。由于大多数指令不做模板转换,所以它不经常使用。需要用到compile去转换模板的例子有ngRepeat,或者异步加载内容,如ngView。编译需要如下参数:

tElement:模板元素,该指令已声明的元素。只有在元素和子元素上进行模板转换是安全的。

tAttr:模板属性,在所有的指令compile函数之间共享的属性。

transclude:一个transclude linking函数-- function(scope, cloneLinkingFn)

备注:如果模板被克隆,那么template实例和link实例是不同的对象。因此,所有在compile函数里克隆的DOM节点做DOM转换都是不安全的。具体来说,DOM监听应该在link函数里而不是在compile函数内。

注意:compile函数不能操作指令去递归使用自身的模板或compile函数。编译这些指令将会导致一个无限循环和堆栈溢出错误。可以通过手动使用postLink函数强制编译指令的模板而不是依靠通过template或templateUrl或在compile函数模板手动编译。

link

如果未定义compile属性,则使用此属性。

function link(scope, iElement, iAttrs,
controller, transcludeFn) { ... }

link函数负责注册DOM监听及更新DOM操作,该函数在模板被克隆后执行。大部分指令逻辑是放在这里面的。

函数参数:

scope:被注册监听的指令使用的作用域。

iElement:元素实例,使用该指令的元素。当子元素已被关联,那么只能在postLink函数内操作是安全的。

iAttrs:属性实例,在这个元素上声明的属性,在所有指令的linking函数内共享。

controller:如果至少有一个指令的元素定义一个控制器,那么是个控制器实例。控制器在所有的指令中被共享,它允许指令使用控制器作为通信通道。

transcludeFn:预绑定到正确的嵌入范围的一个linking函数。范围可以通过一个可选的第一个参数重写--function([scope],
cloneLinkingFn)

pre-linking 函数:在关联子元素之前执行。

Post-linking函数:在关联子元素之后执行。

$compile用法:

$compile(element,transclude,maxPriority);

element:将要被编译和插入模板的元素或者HTML字符串。

transclude:指令内有效的函数。Function(angular.Scope,cloneAttachFn=)

maxPriority:只有在指令比给定的优先级低时应用。只影响根元素,不影响子元素。

返回:

一个用于绑定HTML模板到一个作用域的连接函数。

scope:绑定的作用域。

cloneAttachFn=:如果已提供cloneAttachFn=,则连接函数将克隆模板并且调用cloneAttachFn函数允许去在DOM文档中适当的地方附上克隆的元素。

cloneAttachFn被调用如:

cloneAttachFn(clonedElement,scope);

clonedElement:一个被传递到编译器的被克隆的原始元素。

scope:当前scope和linking函数执行的地方。

调用linking函数返回模板的元素。有另一个原始元素将被传递,或者克隆的元素被提供了cloneAttachFn。

在连接视图之后直到调用一次$digest()才会更新,这是Angular自动完成的。

如果你需要获得绑定的页面,有两个方法完成:

1.如果你不想在传给编译器和保持这个参考范围之前去请求克隆模板和创建DOM元素:var element = $compile(‘<p>{{value}}</p>’)(scope);

2.另一方面,你需要元素被克隆,从原始的例子中的视图引用将不指向克隆,而是将要被克隆的模板。在这种情况下,你可以通过cloneattachfn访问克隆:

  var templateElement = angular.element(‘<p>{{value}}</p>’);
scope = … ;//定义scope
var clonedElement = $compile(templateElement)(scope,function(clonedElement,scope){
//在HTML文档的合适位子添加克隆元素
})

使用代码(注意:jQLite的选择器功能有限,此处引入了jQuery):

  <div ng-app="Demo" ng-controller="testCtrl as ctrl">
<div id="contianer">a</div>
</div>
  (function () {
angular.module("Demo", [])
.service("compileTest", ["$compile",compileTest])
.controller("testCtrl", ["$scope","compileTest",testCtrl])
function compileTest($compile){
this.add = function (s) {
var element = angular.element('<span>{{ctrl.words}}</span>');
angular.element("#contianer").append($compile(element)(s))
}
};
function testCtrl($scope,compileTest){
var e = angular.element("#contianer");
this.words = "A";
compileTest.add($scope);
};
}());

$compile.directive.Attributes

一个包含规范的DOM元素属性并且能在指令的compile和link函数之间共享的对象。这个值反映了当前绑定的状态{{}}。

方法

$addClass(classVal);

classVal指定元素该添加的css类。如果一个动画样式是可执行的,那么触发该动画样式。

$removeClass(classVal);

classVal指定元素该移除的css类。如果一个动画样式是可执行的,那么触发该动画样式。

$updateClass(newClasses,oldClasses);

更新指定元素的css类。newClasses是新的css类,将要替换oldClasses(已存在样式)。

$observe(key,fn);

观察一个在内部插入的属性。当下一次$digest只会,此观察函数将会被执行一次。当内部插入的值发生变化的时候调用一次此函数。

$set(name,value);

设置DOM元素属性值。name:属性名,value:属性值。

属性:

$attr;

元素属性。

使用代码:

  .red{color:red}
.blue{color:blue}
  <div ng-app="Demo" ng-controller="testCtrl as ctrl">
<div class="blue testClass" data-value="value" new-dir>11111</div>
</div>
  (function () {
angular.module("Demo", [])
.directive("newDir",newDir)
.controller("testCtrl",angular.noop)
function newDir(){
return{
restrict:"ACEM",
link:function(scope,element,attrs){
attrs.$addClass("red");
attrs.$removeClass("blue");
attrs.$updateClass("newClass","testClass");
element.bind("mouseover",function(){
attrs.$set("data-text","hello");
});
var count = 0;
attrs.$observe("data-text",function(){
console.log(count++);
});
}
}
};
}());

对于指令这块,真的需要多写多用才能真正的理解这些内容及用法... 这篇关于指令的总结文章没多少直接展示的使用代码,不过每个属性都测试过了用法,也写过一些自己项目用的或者自己写着玩的插件... 好了,暂时写到这,接下来去学习另外的服务...

AngularJs $compile编译服务与指令的更多相关文章

  1. Angular - - $compile编译服务与指令

    $compile 这是个编译服务.编译一段HTML字符串或者DOM的模板, 产生一个将scope和模板连接到一起的函数. 编译服务主要是为指令编译DOM元素,下面的一大段也是主要介绍指令的. 下面是一 ...

  2. Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置

    一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...

  3. Python: 字符串搜索和匹配,re.compile() 编译正则表达式字符串,然后使用match() , findall() 或者finditer() 等方法

    1. 使用find()方法 >>> text = 'yeah, but no, but yeah, but no, but yeah' >>> text.find( ...

  4. centos7下使用n grok编译服务端和客户端穿透内网

    (发现博客园会屏蔽一些标题中的关键词,比如ngrok.内网穿透,原因不知,所以改了标题才能正常访问,) 有时候想在自己电脑.路由器或者树莓派上搭建一些web.vpn等服务让自己用,但是自己的电脑一般没 ...

  5. 在线java反编译服务

    大家是否遇到过有java class文件,却没有java源码的苦恼.近期findmaven.net提供了在线java反编译服务http://www.findmaven.net/decompile_cn ...

  6. 请问一下大佬们,我的项目compile编译的时候总是编译报错

    这是执行compile编译的结果 这是加上参数-X之后的结果

  7. 老吕教程--02后端KOA2框架自动重启编译服务(nodemon)

    上一篇讲完搭建Typescritp版的Koa框架后,F5运行服务端,页面进行正常显示服务. 今天要分享的是,如果要修改服务端代码,如果让编译服务自动重启,免去手动结束服务再重启的过程. 自动重启服务需 ...

  8. angularjs 动态加载指令------编译服务$compile

    场景: 我们写了一个自定义的指令,这条指令需要一些数据,而这些数据需要在某些操作之后才能就绪,这时候,我们就需要在数据就绪之后,动态加载指令. 示例: js: $scope.$watch('repor ...

  9. C文件编译、链接指令

    通过mac终端 输入指令: cc -c 文件名.c 可以把C文件编译成.o文件(其实是2进制文件) 然后通过指令 cc 文件名.o 把.o文件链接C文件所需要的C语言的底层库,成为可以直接运行的lin ...

随机推荐

  1. StackExchange.Redis--纯干货喂饱你

    Redis和StackExchange.Redis redis有多个数据库1.redis 中的每一个数据库,都由一个 redisDb 的结构存储.其中,redisDb.id 存储着 redis 数据库 ...

  2. js的浅拷贝和深拷贝

    转载:http://www.jb51.net/article/91906.htm //深拷贝,并且把合并后的值放到第二个参数里 function deepCopy(p, c) { var c = c ...

  3. 使用 Socket 通信实现 FTP 客户端程序(来自IBM)

    FTP 客户端如 FlashFXP,File Zilla 被广泛应用,原理上都是用底层的 Socket 来实现.FTP 客户端与服务器端进行数据交换必须建立两个套接字,一个作为命令通道,一个作为数据通 ...

  4. Vim块注释

    如何在VIM下快速注释块代码 添加块注释 01.进入视图模式 v进入视图模式,控制方向键选中注释的代码 02.进入列模式并插入# ctrl+v进入列,I插入注释# 03.全部注释 esc两次自动全部注 ...

  5. MVC认知路【点点滴滴支离破碎】【一】----新建数据库

    1.App_Data文件夹创建[SQL Server Compact Local Database *]数据库 2.添加链接字符串<add name="MovieDBContext&q ...

  6. python基础_制作多级菜单_(运用:字典_列表_元组等知识)

    #!/usr/bin/env python # -*- coding:utf-8 -*- #Author: nulige db = {} path = {} while True: temp = db ...

  7. Mybatis学习--spring和Mybatis整合

    简介 在前面写测试代码的时候,不管是基于原始dao还是Mapper接口开发都有许多的重复代码,将spring和mybatis整合可以减少这个重复代码,通过spring的模板方法模式,将这些重复的代码进 ...

  8. 切割haproxy的日志

    日志的切割有以下几种方法: 1.写个定时任务,每天某个时间点把旧的日志重命名,并对服务重启使其重新打开日志并写入. 2.通过管道的方式把新产生的日志写到另外一个日志文件里. 3.通过logrotate ...

  9. Android网络开发之实时获取最新数据

    在实际开发中更多的是需要我们实时获取最新数据,比如道路流量.实时天气信息等,这时就需要通过一个线程来控制视图的更新. 示例:我们首先创建一个网页来显示系统当前的时间,然后在Android程序中每隔5秒 ...

  10. 我的第一个jsp程序-实现注册登录留言功能

    1,注册功能,包括两个页面 zhuce.jsp注册页面 <%@ page language="java" contentType="text/html; chars ...