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/

原文地址:https://www.cnblogs.com/darrenji/p/4975374.html