在学习自定义指令,分享一篇文章。
angular建立自定义指令使用directive()例如:css
var app = angular.module('myapp',[]);
app.directive('helloWorld',function(){app
return { restrict: 'AE', //推荐使用A replace: true, //template会覆盖掉自定义标签 template: '<h3>Hello World!</h3>' //自定义标签要显示的内容 }
});
建立出来的便签推荐使用<div hello-world></div>函数
第一个参数是指令的名称学习
第二个参数是一个返回指令定义对象的函数。若是你的指令对额外的对象/服务(services)例如 $rootScope, $http 或者 $compile 有依赖,它们也能够在其中被注入。rest
link函数和做用域code
link函数是负责操做DOM元素,例如:对象
app.directive('helloWorld',function(){继承
return { restrict: 'AE', replace: true, template: '<p></p>', link: function(scope,elem,attr){ elem.bind('click',function(){ elem.css('background-color','white'); scope.$apply(function(){ scope.color = "white"; }); }); elem.bind('mouseover',function(){ elem.css('cursor','pointer'); }); } }
});
注意到link函数被用在了指令中。它接收三个参数:seo
scope – 它表明指令被使用的做用域。在上面的例子中它等同于符控制器的做用域。
elem – 它表明绑定指令的元素的jQlite(jQuery的一个本身)包裹元素。若是你在AngularJS被包含以前就包括了jQuery,那么它将变成jQuery包裹元素。因为该元素已经被jQuery/jQlite包裹,咱们没有必要将它包含在$()中来进行DOM操做。
attars – 它表明绑定指令的元素上的属性。例如,若是你在HTML元素上有一些指令形式为:<hello-world some-attribute></hello-world>,你能够在link函数内用attrs.someAttribute来引用这些属性。
link函数主要是用来对DOM元素绑定事件监听器,监视模型属性变化,并更新DOM。在前面的指令代码中,咱们绑定了两个监听器,click和mouseover。click处理函数重置了队列
的背景颜色,而mouseover处理函数则将游标改变为pointer。模板中拥有表达式{{color}},它将随着父做用域中的模型color的变化而变化,从而改变了Hello World的背景色。
Compile函数
Compile函数主要用来在link函数运行以前进行一些DOM转化。它接收下面几个参数:
tElement – 指令绑定的元素
attrs – 元素上声明的属性
这里要注意compile不可以访问scope,并且必须返回一个link函数。可是,若是没有compile函数以依然能够配置link函数。compile函数能够被写成下面的样子:
app.directive('test',function(){
return { compile: function(tElem,attrs){ //在这里原则性的作一些DOM转换 return function(scope,elem,attrs){ //这里编写link函数 } } }
});
何时使用compile?
大多数时候,你仅仅只须要编写link函数。这是由于大部分指令都只关心与注册事件监听器,监视器,更新DOM等等,它们在link函数中便可完成。像是ng-repeat这样的指令,须要屡次克隆并重复DOM元素,就须要在link函数运行以前使用compile函数。你可能会问威慑呢么要将两个函数分别使用。为何咱们不能只编写一个函数?为了回答这个问题咱们须要理解Angular是如何编译指令的!
指令是如何被编译的
当应用在启动时,Angular开始使用$compile服务解析DOM。这项服务会在标记中寻找指令而后将它们各自匹配到注册的适龄。一旦全部的指令都已经被识别完成,Angular就开始执行它们的compile函数。正如前面所提到的,compile函数返回一个link函数,该函数会被添加到稍后执行的link函数队列中。这叫作编译阶段(compile phase)。注意到即便同一个指令有几个实例存在,compile函数也只会运行一次。
在编译阶段以后就到了连接阶段(link phase),这时link函数就一个接一个的执行。在这个阶段中模板被生成,指令被运用到正确的做用域,DOM元素上开始有了事件监听器。不像是compile函数,lin函数会对每一个指令的实例都执行一次。
改变指令的做用域
默认状况下指令应该访问父做用域。可是咱们并不像对全部状况一律而论。若是咱们对指令暴露了父控制器的scope,那么指令就能够自由的修改scope属性。在一些状况下你的指令可能想要添加一些只有内部可使用的属性和函数。若是咱们都在父做用域中完成,可能会污染了父做用域。所以,咱们有两种选择:
一个子做用域 – 这个做用域会原型继承父做用域。
一个隔离的做用域 – 一个全新的、不继承、独立存在的做用域。
做用域能够由指令定义对象中的scope属性定义。下面的例子展现了这一点:
app.directive('helloWorld',function(){
return { scope: true, //使用一个继承父做用域的自做用域 restrict: 'AE', replace: true, template: '<h3>Hello World!</h3>' }
});
上面的代码要求Angular为指令提供一个可以原型继承父做用域的子组用于。另外一种情形,一个隔离做用域,代码以下所示:
app.directive('helloWorld',function(){
return { scope: {}, //使用一个全新的隔离做用域 restrict: 'AE', replace: true, template: '<h3>Hello World!</h3>' }
});
上面的指令使用一个不继承父做用域的全新隔离做用域。当你想要建立一个可重用的组件时隔离做用域是一个很好的选择。经过隔离做用域咱们确保指令是自包含的兵能够轻松地插入到任何HTML app中。这种作法防止了父做用域被污染,因为它不可访问父做用域。在咱们修改后的helloWorld指令中若是你将scope设置为{},那么代码就不会再正常运行。它将建立一个隔离的做用域而后表达式{{color}}将没法引用隔离做用域中的属性所以值变为undefined。
隔离做用域并不意味着你一点都不能获取到父做用域中的属性。有一些技巧可使你访问父做用域中的属性同时监听这些属性的变化。咱们将在下一篇文章中提到这种高级技巧。
原文地址:http://www.xgllseo.com/?p=3511