AngularJS自定义控件实例详解(3)

compile() 和 link() 的命名相当混乱。它们肯定是受编译队伍的启发而命名的。我可以看到相似点,不过一个编译器是传入一次,然后输出。而指令则是配置一次 HTML 元素,然后在之后的 $scope 对象改变时进行更新。

compile() 函数如果叫做 create(), init() 或者 configure()也许会更好。这样可以表达出这个函数只会被调用一次的意思。

而 link() 函数如果叫 bind() 或者 render() 也许会更好,能更好的表达出这样的意思,在指令绑定数据或者重绑定数据的时候,这个函数将会被调用。

下面是一个完整的例子,演示了指令使用 compile() 和 link() 函数的:

<!-- lang: js --> <div ng-controller="MyController" > <userinfo >This will be replaced</userinfo> </div> <script> myapp = angular.module("myapp", []); myapp.directive('userinfo', function() { var directive = {}; directive.restrict = 'E'; /* restrict this directive to elements */ directive.compile = function(element, attributes) { element.css("border", "1px solid #cccccc"); var linkFunction = function($scope, element, attributes) { element.html("This is the new content: " + $scope.firstName); element.css("background-color", "#ffff00"); } return linkFunction; } return directive; }) myapp.controller("MyController", function($scope, $http) { $scope.cssClass = "notificationDiv"; $scope.firstName = "Jakob"; $scope.doClick = function() { console.log("doClick() called"); } }); </script>

compile() 函数设置 HTML 元素的 border 。它只执行一次,因为 compile() 函数只执行一次。

link() 替换 HTML 元素内容,并且把背景颜色设置为黄色。

把设置 border 放在 compile(), 把背景颜色放在 link() 没啥特别的理由。你可以把所有的操作都丢到 compile(),或者都放到 link()。如果都放到 compile() 它们只会被设置一次(你需要它们是常量的话)。如果放到了 link(),它们会在每次 HTML 元素被绑到 $scope 的时候都发生变化。当你希望根据 $scope 中的数据来设置 boarder 和背景颜色的时候这非常有用。

只设置 link() 函数

有时候你的指令可能不需要 compile() 。你只需要用到 link()。这种情况下,你可以直接设置指令定义对象中的 link() 函数。下面是一个对上面例子的修改,只用 link 函数:

<!-- lang: js --> <div ng-controller="MyController" > <userinfo >This will be replaced</userinfo> </div> <script> myapp = angular.module("myapp", []); myapp.directive('userinfo', function() { var directive = {}; directive.restrict = 'E'; /* restrict this directive to elements */ directive.link = function($scope, element, attributes) { element.html("This is the new content: " + $scope.firstName); element.css("background-color", "#ffff00"); } return directive; }) myapp.controller("MyController", function($scope, $http) { $scope.cssClass = "notificationDiv"; $scope.firstName = "Jakob"; $scope.doClick = function() { console.log("doClick() called"); } }); </script>

注意 link() 方法和之前例子中返回的 link() 是完全一样的。

通过 Transclusion 封装元素的指令

到目前为止,我们看到的所有例子,都是把匹配到的元素内容给替换为指令的指定内容,不管是通过 Javascript 也好或者 HTML 模板也好。不过如果遇到内容中有部分是开发者可以指定的内容的时候呢?比如说:

<!-- lang: js --> <mytransclude>This is a transcluded directive {{firstName}}</mytransclude>

标记为 <mytransclude> 的元素,它的部分内容可以由开发者设置。因此,这部分 HTML 不应该被指令的 HTML 模板给替换。我们实际上是希望这部分 HTML 由 AngularJS 来处理的。这个处理叫做 “transclusion”。 1

为了能让 AngularJS 把这部分 HTML 放到指令内部处理,你必须设置指令定义对象的 transclude 属性为 true。你还需要告诉 AngularJS,指令的 HTML 模板中哪一部分需要把 transcluded HTML 包含进来。你可以通过插入 ng-transclude 属性 (实际上,是一个指令) 到 HTML 模板的 HTML 元素中,标记你想要添加 transcluded HTML 的元素。

下面是一个 AngularJS 指令,演示如何使用 transclusion:

<!-- lang: js --> <mytransclude>This is a transcluded directive {{firstName}}</mytransclude> <script> myapp = angular.module("myapp", []); myapp.directive('mytransclude', function() { var directive = {}; directive.restrict = 'E'; /* restrict this directive to elements */ directive.transclude = true; directive.template = "<div ng-transclude></div>"; return directive; }); myapp.controller("MyController", function($scope, $http) { $scope.firstName = "Jakob"; }); </script>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjfpsj.html