Angular - - $compile编译服务与指令
$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。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="testCtrl as ctrl">
<div id="contianer">a</div>
</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 vm = this;
var e = angular.element("#contianer");
vm.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">
<div ng-controller="testCtrl as ctrl">
<div class="blue testClass" data-value="value" new-dir>11111</div>
</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++);
});
}
}
};
}());
对于指令这块,真的需要多写多用才能真正的理解这些内容及用法... 这篇关于指令的总结文章没多少直接展示的使用代码,不过每个属性都测试过了用法,也写过一些自己项目用的或者自己写着玩的插件... 好了,暂时写到这,接下来去学习另外的服务...
Angular - - $compile编译服务与指令的更多相关文章
- AngularJs $compile编译服务与指令
$compile 这是个编译服务.编译一段HTML字符串或者DOM的模板, 产生一个将scope和模板连接到一起的函数. 编译服务主要是为指令编译DOM元素,下面的一大段也是主要介绍指令的. 下面是一 ...
- Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置
一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...
- Python: 字符串搜索和匹配,re.compile() 编译正则表达式字符串,然后使用match() , findall() 或者finditer() 等方法
1. 使用find()方法 >>> text = 'yeah, but no, but yeah, but no, but yeah' >>> text.find( ...
- centos7下使用n grok编译服务端和客户端穿透内网
(发现博客园会屏蔽一些标题中的关键词,比如ngrok.内网穿透,原因不知,所以改了标题才能正常访问,) 有时候想在自己电脑.路由器或者树莓派上搭建一些web.vpn等服务让自己用,但是自己的电脑一般没 ...
- 在线java反编译服务
大家是否遇到过有java class文件,却没有java源码的苦恼.近期findmaven.net提供了在线java反编译服务http://www.findmaven.net/decompile_cn ...
- 请问一下大佬们,我的项目compile编译的时候总是编译报错
这是执行compile编译的结果 这是加上参数-X之后的结果
- 老吕教程--02后端KOA2框架自动重启编译服务(nodemon)
上一篇讲完搭建Typescritp版的Koa框架后,F5运行服务端,页面进行正常显示服务. 今天要分享的是,如果要修改服务端代码,如果让编译服务自动重启,免去手动结束服务再重启的过程. 自动重启服务需 ...
- angularjs 动态加载指令------编译服务$compile
场景: 我们写了一个自定义的指令,这条指令需要一些数据,而这些数据需要在某些操作之后才能就绪,这时候,我们就需要在数据就绪之后,动态加载指令. 示例: js: $scope.$watch('repor ...
- C文件编译、链接指令
通过mac终端 输入指令: cc -c 文件名.c 可以把C文件编译成.o文件(其实是2进制文件) 然后通过指令 cc 文件名.o 把.o文件链接C文件所需要的C语言的底层库,成为可以直接运行的lin ...
随机推荐
- SystemClock.sleep和Thread.sleep的区别
在Java中我们处理线程同步问题时,处理延迟可能会使用Thread类的sleep方法,这里抛开concurrent类的一些方法,其实 Android平台还提供了一个SystemClock.sleep方 ...
- Socket在手机上的应用
usb读取:pid vid --可以唯一的确定设备获取手机驱动socket固定端口通信 wifipc机在局域网内,udp的数据包(整个网段) 蓝牙配对 bluetoothsocket 如果放大:可以分 ...
- 【转】The magic behind array length property
Developer deals with arrays every day. Being a collection, an important property to query is the num ...
- hihocoder 网络流二·最大流最小割定理
网络流二·最大流最小割定理 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? ...
- apk文件分析原则
如果在dex生成的jar文件里没有发现关键内容的话,就要注意jar里面的native函数以及loadlibrary操作,从而可以判断出加载了哪些so,调用了什么函数.就不会出现判断不出是不是加载了某s ...
- 线程pthread_create()、pthread_exit()、pthread_join()、pthread_cancel()
- Arduino IDE 添加DHT11传感器第三方库的方法
由于Arduino本身没有DHT 11温湿度传感器的的头文件,单有第三方的库可以给我门使用.方法如下: Step 1:如果你已经下载了最新版的Arduino IDE就可以使用其自带的库管理器和版型管理 ...
- 各种命令,以及FAQ..持续更新.....
Linux 篇: CentOs 7 修改主机名 hostnamectl --static set-hostname <host-name> 统计最多的10条记录 awk '{print $ ...
- Chapter 1 First Sight——2
"Bella," my mom said to me — the last of a thousand times — before I got on the plane. &qu ...
- <c:foreach> 标签怎么获取循环次数?
<c:forEach var="i" begin="1" end="9" varStatus="status"&g ...