angular 中的自定义指令之详解API
在ng中指令相关api在 这里 也许归类不明确,后期再整理,博客会一直被维护
自定义属性的四种类别
分为: 元素E,属性A,注释M,类C , 分别如下:
my-dir><span my-dir="exp">span><span class="my-dir: exp;">span>
简单创建一个指令
html结构:
<div ng-controller="myCtrl"><div my-customer>div>
div>
javascript结构:
angular.module('myApp', []).controller('myCtrl', ['$scope', function($scope) {$scope.customer = {name: 'Naomi',address: '1600 Amphitheatre'};}]).directive('myCustomer', function() {return {template: 'Name: {{customer.name}} Address: {{customer.address}}'};});
输出:
Name: Naomi Address: 1600 Amphitheatre
说明: 此处,myCtrl 中定义的 $scope.customer 属性和属性值都在指令中的模板使用了。同样的,在指令return 对象中的 template 也可被替换成一路径,在路径html中书写和template中同样的代码,使用这种方式,可以操作更多代码。
templateUrl 函数式编程
html结构:
<div ng-controller="myCtrl"><div my-customer>div>
div>
javascript结构:
angular.module('myApp', []).controller('myCtrl', ['$scope', function($scope) {$scope.customer = {name: 'Naomi',address: '1600 Amphitheatre'};}]).directive('myCustomer', function() {return {templateUrl: function(elem, attr) {return 'customer-' + attr.type + '.html';}};});
不同的templateUrl ①
Name: {{customer.name}}
不同的templateUrl ②
Address: {{customer.address}}
输出结果:
Name: Naomi
Address: 1600 Amphitheatre
说明: templateUrl 的值可以是一个函数返回值,返回用于指令中的html模板的url。
隔离指令的作用域
① 通过不同的controller
html结构:
<div ng-app="myApp"><div ng-controller="myCtrl1"><my-customer>my-customer>div><div ng-controller="myCtrl2"><my-customer>my-customer>div>
div>
javascript结构:
angular.module('myApp', []).controller('myCtrl1', ['$scope', function($scope) {$scope.customer = {name: 'Naomi',address: '1600 Amphitheatre'};}]).controller('myCtrl2', ['$scope', function($scope) {$scope.customer = {name: 'Igor',address: '123 Somewhere'};}]).directive('myCustomer', function() {return {restrict: 'E',templateUrl: 'my-customer.html'};});
templateUrl html 结构:
Name: {{customer.name}} Address: {{customer.address}}
输出结果:
Name: Naomi Address: 1600 AmphitheatreName: Igor Address: 123 Somewhere
说明: 可见 不同的controller 有不同的作用范围。虽然指令一样,每次渲染都是分离的,所以我们可以抽象出来指令,用于html模板和代码的重用,封装。但是这样又不是很好,因为用了两个controller,我们可以使用指令中的scope而不是controller里的scope来替代,具体做法是将外部的scope 映射到指令内部的scope, 如下:
② 通过指令属性映射scope
html结构:
<div ng-app="myApp" ng-controller="myCtrl"><my-customer info="naomi">my-customer><my-customer info="igor">my-customer>
div>
javascript 结构:
angular.module('myApp', []).controller('myCtrl', ['$scope', function($scope) {$scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' };$scope.igor = { name: 'Igor', address: '123 Somewhere' };}]).directive('myCustomer', function() {return {restrict: 'E',scope: {customerInfo: '=info'},templateUrl: 'my-customer-iso.html'};});
templateUrl html结构:
Name: {{customerInfo.name}} Address: {{customerInfo.address}}
编译后的html结果:
Name: Naomi Address: 1600 AmphitheatreName: Igor Address: 123 Somewhere
③ 指令中的如果定义scope属性则html中的scope不会直接继承controller中的scope,在html中使用的都需要在scope:{}中声明,否则就是undefined
html 结构:
<div ng-app="myApp" ng-controller="myCtrl"><my-customer info="naomi">my-customer>div>
javascript结构:
angular.module('myApp', []).controller('myCtrl', ['$scope', function($scope) {$scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' };$scope.vojta = { name: 'Vojta', address: '3456 Somewhere Else' };}]).directive('myCustomer', function() {return {restrict: 'E',scope: {customerInfo: '=info'},templateUrl: 'my-customer-plus-vojta.html'};});
templateUrl html结构:
Name: {{customerInfo.name}} Address: {{customerInfo.address}}
<br>
Name: {{vojta.name}} Address: {{vojta.address}}
html编译后的结果:
Name: Naomi Address: 1600 Amphitheatre
Name: Address:
说明: vojta 在指令中的scope没有被定义,不会直接继承在controller中的,那么他就是undefined,所以就是空白(什么都不显示)
可操作DOM的指令
创建一个用于操作dom的指令,如果需要dom操作也都应该放在指令里。
html 结构:
<div ng-app="myApp" ng-controller="myCtrl">Date format: <input ng-model="format"> <hr/>Current time is: <span my-current-time="format">span>div>
javascript结构:
angular.module('myApp', []).controller('myCtrl', ['$scope', function($scope) {$scope.format = 'M/d/yy h:mm:ss a';}]).directive('myCurrentTime', function($interval, dateFilter) {return {restrict: 'AE',link: function(scope, element, attr){var format, timeoutId;/* 更新时间函数 */function updateTime() {element.text(dateFilter(new Date(), format));}/* 监视时间格式的改变 */var attrWatch = scope.$watch(attrs.myCurrentTime, function(value) {format = value;updateTime();});/* 定时器 */timeoutId = $interval(function() {updateTime(); // update DOM}, 1000);/* 页面跳转后移除定时器防止内存泄露 */element.on('$destroy', function() {$interval.cancel(timeoutId);attrWatch(); // 移除watch});}};});
说明: 在link函数中,操作dom节点,让dom的文本节点动态显示时间跳动。在页面跳转之后及时清除定时器和监视器以免发生内存泄漏。
通过transclude和ng-transclude创建可包裹其他元素的指令
html结构:
<div ng-app="myApp" ng-controller="myCtrl"><my-dialog>Check out the contents, {{name}}!my-dialog>div>
javascript结构:
angular.module('myApp', []).controller('myCtrl', ['$scope', function($scope) {$scope.name = 'Tobias';}]).directive('myDialog', function() {return {restrict: 'E',transclude: true,scope: {},templateUrl: 'my-dialog.html',link: function(scope) {scope.name = 'Jeff';}};
});
templateUrl html 结构:
<div class="alert" ng-transclude>div>
编译后的html结构:
Check out the contents, Tobias!
说明: 指令中的scope本应隔离controller中的作用域的,但是由于设置了transclude=true选项,scope就会继承controller中的定义,所以最终是Tobias而不是Jeff。
未完。。。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
