野兽的Angular Api 学习、翻译及理解 - - $compile编译服务与指令

野兽的ng api学习 -- $compile

$compile

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

编译服务主要是和指令为指令服务,下面的文章也是主要介绍指令的。

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

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。terminal

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

scope

如果设置为true,那么该指令将会创建一个新(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文档的合适位子添加克隆元素

})

使用代码:

<div ng-app="Demo">

<div ng-controller="demoCtrl">

<div id="contianer">a</div>

</div>

</div>

<script>

angular.module("Demo", [])

.service("compileTest", ["$compile", "$document", function
($compile, $document) {

var self = this;

self.add = function (s) {

var element
= angular.element(‘<span>{{words}}</span>‘);

angular.element("#contianer").append($compile(element)(s))

}

}])

.controller("demoCtrl", ["$scope", "compileTest", function
($scope, compileTest) {

var e =
angular.element("#contianer");

$scope.words = "A";

compileTest.add($scope);

}])

</script>

$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;

元素属性。

使用代码:

<style>

.red{

color:red

}

.blue{

color:blue

}

</style>

<div ng-app="Demo">

<div ng-controller="demoCtrl">

<div class="blue testClass" data-value="value" new-dir>11111</div>

</div>

</div>

<script>

angular.module("Demo",[])

.directive("newDir",function(){

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++);

});

}

}

})

.controller("demoCtrl",["$scope",function($scope){

}])

</script>

如果刚学ng的小伙伴们觉得看完这篇就能说理解了指令,那野兽也就跪着呵呵了,对于指令这块,真的需要多写多用才能真正的理解这些内容及用法... 这篇关于指令的总结文章没多少直接展示的使用代码,不过每个属性都测试过了用法,也写过一些自己项目用的或者自己写着玩的插件... 好了,暂时写到这,接下来去学习另外的服务...

时间: 2024-10-28 20:22:09

野兽的Angular Api 学习、翻译及理解 - - $compile编译服务与指令的相关文章

野兽的Angular Api 学习、翻译及理解 - - $sce 和 $sceDelegate

野兽的ng api学习 -- $sce 和 $sceDelegate $sce $sce 服务是AngularJs提供的一种严格上下文逸出服务. 严格上下文逸出服务(翻译水平有限,较渣...) 严格上下文逸出(SCE)是一种需要在一定的语境中导致AngularJS绑定值被标记为安全使用语境的模式.由用户通过ng-bind-html绑定任意HTML语句就是这方面的一个例子.我们称这些上下文语境为特权或者SCE. 下面代码是简化了的ngBindHtml实现(当然,这不是完整版ngBindHtml源码

野兽的Angular Api 学习、翻译及理解 - - ngReadonly、ngSelected、ngDisabled

野兽的 ng api 学习 - - ngReadonly.ngSelected.ngDisabled ngReadonly 该指令将input,textarea等文本输入设置为只读. HTML规范不允许浏览器保存类似readonly的布尔值属性.如果我们将一个Angular的插入值表达式转换为这样的属性,那么当浏览器删除该属性时,绑定信息就会丢失.这个指令不被浏览器删除,并且提供了一个永久性的可靠的地方来存储绑定信息. 格式:ng-readonly=“value” value:表达式   结果为

野兽的Angular Api 学习、翻译及理解 - - $location 和 $window

野兽的ng api学习 -- $location 和 $window $location $location服务解析浏览器地址中的url(基于window.location)并且使url在应用程序中可用.将地址栏中的网址的变化反映到$location服务和$location的变化反映到浏览器地址栏. 公开浏览器地址栏中的当前网址,这样就可以: 1.观察和监听网址. 2.改变网址. 与浏览器url同步当用户: 1.改变地址栏的值. 2. 单击“后退”或“前进”按钮(或单击“历史链接”). 3.点击

野兽的Angular Api 学习、翻译及理解 - - form.FormController、ngModel.NgModelController

野兽的ng api学习 -- form.FormController.ngModel.NgModelController form.FormController FormController跟踪所有他所控制的和嵌套表单以及他们的状态,就像有效/无效或者脏值/原始. 每个表单指令创建一个FormController实例. 方法: $addControl(); 给表单注册一个控制器. 使用了ngModelController的输入元素会在连接时自动执行. $removeControl(); 给表单注

@野兽的Angular Api 学习、翻译及理解 - - angular.module

@野兽的 ng api 学习 -- angular.module angular.module 创建一个全局的可用于检索和注入的Angular模块.所有Angular模块(Angular核心模块或者第三方模块)想要在应用里实现,都需要使用这个注入机制. 格式:angular.module(name,[requires],[configFn]); name :  string  创建的模块名称. [requires]: 字符串的数组  代表该模块依赖的其他模块列表,如果不依赖其他模块,则为空数组.

野兽的Angular Api 学习、翻译及理解 - - ngRoute Angular自带的路由

野兽的ng api学习 -- ngRoute ngRoute $routeProvider 配置路由的时候使用. 方法: when(path,route); 在$route服务里添加一个新的路由. path:该路由的路径. route:路由映射信息. controller:字符串或函数,指定控制器. controllerAs:一个用于控制器的标识符名称.. template:字符串或函数,html模板. templateUrl:字符串或函数,html模板的地址. resolve:对象,一个可选的

野兽的Angular Api 学习、翻译及理解 - - $templateCache 和 $templateRequest

野兽的ng api学习 -- $templateCache 和 $templateRequest $templateCache 第一次使用模板,它被加载到模板缓存中,以便快速检索.你可以直接将模板标签加载到缓存中,或者通过$templateCache服务. 通过script标签: <script type=”text/ng-template” id=”template.html”> <p>This is the content of the template</p> &

野兽的Angular Api 学习、翻译及理解 - - $q 承诺与延迟

野兽的ng api学习 -- $q $q 一个帮助处理异步执行函数的服务.当他们做完处理时,使用它们的返回值(或异常). 受 Kris Kowa’s Q 的启发,这是一个实现promise/deferred对象的启用. $q的两种方式---这是一个更类似于Kris Kowal Q或jQuery的递延实现,另一种在一定程度上类似的ES6承诺. Deferred Api 一个被$q.defer()调用的deferred的新实例. deferred对象的目的是暴露相关承诺实例,以及APIs被执行的成功

野兽的Angular Api 学习、翻译及理解 - - $animate

野兽的ng api学习 -- $animate $animate $animate服务提供了基本的DOM操作功能如在DOM里插入.移除和移动元素,以及添加和删除类.这个服务是ngAnimate的核心服务,为CSS和Javascript提供了高档次的动画. $animate在Angular核心都是有效的,无论如何,这个服务为了支持所有动画须包含ngAnimate模块.否则,$animate只能做简单的DOM操作. 方法: enter(element,parent,after,[done]); 在D