AngularJS自定义Directive初体验
通常我们这样定义个module并随之定义一个controller.
var app = angular.module('myApp', []); app.controller('CustomersController', ['$scope', function($scope){ var counter = 0; $scope.customer = { name:'', street:'' }; $scope.customers = [ { name:'', street:'' }, ... ]; $scope.addCustomer = function(){ counter++; $scope.customers.push({ name:'' + counter, street: coutner + '' }); $scope.changeData = function(){ counter++; $scope.customer = { name: '', street:counter + '' }; } } }]);
■ 使用ng-include引用子视图
在一个子视图中可以使用CustomersController,子视图的名称是:child.html
Name:{{customer.Name}}
Street:{{customer.street}}
然后在一个主视图中比如是index.html使用子视图:
<div ng-include="child.html"></div>
■ 初识自定义directive
如果使用自定义directive也可以做到。
angular.module('myApp').directive('myInfo', function(){ return{ template:'Name:{customer.name}<br/>Street:{{customer.street}}' }; })
在index.html主视图中可以这样使用自定义的directive。
<div my-info></div>
为什么myInfo到了视图中变成了my-info?这是一个惯例,比如我们经常用到的ng-repeat,在AngularJS中的源代码中是ngRepeat。还有,为什么,自定义的名称为myInfo的directive可以使用CustomersController的scope呢?因为主视图index.html中使用了CustomersController,而同在index.html视图中的<div my-info></div>共享了CustomersController的scope。
directive通常的用法包括如下:
angular.module('modulename') .directive('myDirective', function(){ return { restrict: 'EA', //E表示element, A表示attribute,C表示class,M表示commnent,即注释 scope:{ title: '@' //@读属性值,=双向绑定,&用户函数 } template: '<div>{{myVal}}</div>', templateUrl: 'app/sample.html', controller: 'myController', link:function($scope, element, attrs){}//DOM操作 }; })
■ 自定义direcitve操作DOM元素
app.directive('myDomDirective', function(){ return { link: function($scope, ele, attrs){ ele.bind('click', function(){ ele.html(''); }); ele.bind('mouseenter', function(){ ele.css('background-color','red'); }); ele.bind('mouseleave', function(){ ele.css('background-color','white'); }); } }; });
在页面中这样使用:
<div my-dom-directive></div>
■ 封闭自定义directive的scope
默认情况下,自定义的directive的会共享父scope,但是,有时候我们希望自定义的directive的scope是封闭的、独立的,比如希望自定义的direcitve被用在多处。
只需要加上scope属性就好了,如下:
angular.module('myDirecitve', function(){ return { scope:{}, template: '' } });
scope属性接受一个对象,在该对象中可以定义独立scope内的属性,而属性值的写法有三种,分别是@,=,&
● 使用@,外部scope赋值不影响封闭scope中的变量
angular.module('myApp').directive('myIsolateScopeWithName', function(){ return { scope:{ name: '@' }, template: 'Name:{{name}}', controller: 'MyController' }; });
在封闭的scope中定义了一个name变量,占位符@表示这里接受一个值。
如何给这里的变量赋值呢?
一种是把name成为一个属性来接收值:
<div my-isolated-scope-with-name name="{{ customer.name }}"></div>
一种是在MyController中给name赋值:
$scope.name = '';
如果把name="{{ customer.name }}"改成myname="{{ customer.name }}"呢?
那就需要这样定义:
angular.module('myApp').directive('myIsolateScopeWithName', function(){ return { scope:{ name: '@myname' }, template: 'Name:{{name}}', controller: 'MyController' }; });
● 使用=,外部scope赋值会影响封闭scope中的变量
angular.module('myApp').directive('myIsolateScopeWithEqual', function(){ return { scope:{ customer: '=' }, template: '<ul><li ng-repeate="prop in customer">{{prop}}</li></ul>' }; });
注意,这里的customer是作为变量在使用,而不是{{customer}},一旦外部的赋值发生变化会影响独立scope中的customer变量值。同样,一旦独立scope中的customer值发生变化,也会影响外部的scope的customer属性值。
外部这样使用:
<div my-isolated-scope-with-equal customer="customer"></div>
● 使用&,允许外部scope传递一个函数给封闭scope
angular.module('myApp').directive('myIsolateScopeWithFunction', function(){ return { scope: { datasource: '=', action:'&' }, template: '<ul><li ng-repeat="prop in datasource">{{ prop }}</li></ul> ' + '<button ng-click="action()">Change Data</button>' }; });
这样使用这个directive
<div my-isolated-scope-with-function datasource="customer" action="changeData()"> </div>
changeData方法被定义在了controller里面:
$scope.changeData = function () { counter++; $scope.customer = { name: 'James', street: counter + ' Cedar Point St.' }; };
如何让外部scope传递一个带参函数给封闭scope呢?
angular.module('directivesModule').directive('isolatedScopeWithController', function () { return { restrict: 'EA', scope: { datasource: '=', add: '&', }, controller: function ($scope) { ... $scope.addCustomer = function () { //Call external scope's function var name = 'New Customer Added by Directive'; $scope.add({ name: name }); //Add new customer to directive scope $scope.customers.push({ name: name, street: counter + ' Main St.' }); }; }, template: '<button ng-click="addCustomer()">Change Data</button>' + '<ul><li ng-repeat="cust in customers">{{ cust.name }}</li></ul>' }; });
在页面中这样调用:
<div isolated-scope-with-controller datasource="customers" add="addCustomer(name)"></div>
■ 允许自定义的direcitve被嵌套
只要把tranclude设置成true就可以。
"use strict"; angular.module("psFramework").directive("psFramework",function(){ return { transclude: true, scope:{ title: '@', subtitle:'@', iconFile:'@' }, controller: "psFrameworkController", templateUrl: "ext-modules/psFramework/psFrameworkTemplate.html" }; })
然后在页面中就可以这样使用:
<ps-framework title="", subtile="", icon-file="">
<ps-menu>
...
</ps-menu>
</ps-framework>
参考:https://weblogs.asp.net/dwahlin/