Angularjs學習筆記指令

wangliuzhan發表於2019-02-16

自定義指令

angularjs中有很多內建指令,一般都是以ng開頭的;比如:ng-app,ng-click,ng-repeat等等。本文介紹angularjs的自定義指令的用法。

指令的定義

首先在html標籤處設定ng-app的屬性值,然後在js檔案中就可以呼叫angular.module得到一個module,最後就可以用module.directive定義一個指令。程式碼如下:

html檔案

<!DOCTYPE html>
<html ng-app="directive">
<head lang="en">
    <meta charset="UTF-8">
    <title>directive</title>
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="./directive.js"></script>
</head>
<body>

    <div my-directive></div>
</body>
</html>

js檔案

var app = angular.module(`directive`,[]);
app.directive(`myDirective`,function(){
   return {
       restrict:"A",
       require:true,
       template:"<span>hello angular</span>",
   };
});

這個例子只使用了directive的最簡單的引數配置,下面是一個詳細的引數配置列表

app.directive(`myDirective`, function factory(injectables) {
    return {
        restrict: string,//指令的使用方式,包括標籤,屬性,類,註釋
        priority: number,//指令執行的優先順序
        template: string,//指令使用的模板,用HTML字串的形式表示
        templateUrl: string,//從指定的url地址載入模板
        replace: bool,//是否用模板替換當前元素,若為false,則append在當前元素上
        transclude: bool,//是否將當前元素的內容轉移到模板中
        scope: bool or object,//指定指令的作用域
        controller: function controllerConstructor($scope, $element, $attrs, $transclude){...},//定義與其他指令進行互動的介面函式
        require: string,//指定需要依賴的其他指令
        link: function postLink(scope, iElement, iAttrs) {...},//以程式設計的方式操作DOM,包括新增監聽器等
        compile: function compile(tElement, tAttrs, transclude){
            return: {
                pre: function preLink(scope, iElement, iAttrs, controller){...},
                post: function postLink(scope, iElement, iAttrs, controller){...}
            }
        }
    };
});

下面介紹幾個常用的引數

restrict

四個值”A”,”E”,”C”,”M”,分別程式碼屬性,標籤,類,註釋,如下:

restrict:"A"   <div my-directive></div>
restrict:"E"   <my-directive></my-directive>
restrict:"C"   <div class="my-diretive"></div>
restrict:"M"   <!--directive:my-directive-->

只測試了A和E的值,感興趣的朋友可以測試一下其他。

template 和 templateUrl

這兩個引數只需要設定一個就行。

transclude

該引數的意思是替換指令的內容,更改上面的例子。html更改部分

<div my-directive>hello angular</div>

js更改部分

 app.directive(`myDirective`,function(){
    return {
        restrict:"A",
        require:true,
        transclude:true,//增加transclude引數的設定
        template:"<div><span ng-transclude></span></div>",//將指令的內容替換到span標籤下
    };
 });

scope

false               預設值。使用父作用域作為自己的作用域
true                新建一個作用域,該作用域繼承父作用域
javascript物件       

當scope為javascript物件時,鍵值對的形式定義。直接看例子吧!
html:

<!DOCTYPE html>
<html ng-app="directive">
<head lang="en">
    <meta charset="UTF-8">
    <title>directive</title>
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="./directive.js"></script>
</head>
<body>
    <div ng-controller="directive">
        <div my-directive etitle="title">{{text}}</div>
    </div>
</body>
</html>

js:

var app = angular.module(`directive`,[]);
app.directive(`myDirective`,function(){
    return {
        restrict:`A`,
        template:`<div><span style="background-color:red;">{{mytitle}}</span><div ng-transclude></div></div>`,
        require:true,
        replace:true,
        transclude:true,
        //將etitle屬性繫結到父控制器的scope域中
        scope:{
            mytitle:`=etitle`
        },
    }
});
app.controller(`directive`,function($scope){
    $scope.title = "學習";
    $scope.text = "angular js概念多";
});

link

link的值是一個function,一般用在在dom上繫結動作的。請看下面實現的一個摺疊皮膚的例子。

<!DOCTYPE html>
<html ng-app="directive">
<head lang="en">
    <meta charset="UTF-8">
    <title>directive</title>
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="./directive.js"></script>
</head>
<body>
    <div ng-controller="directive">
        <expander etitle="title">{{text}}</expander>
    </div>
</body>
</html>
var app = angular.module(`directive`,[]);
app.directive(`expander`,function(){
    return {
        restrict:`E`,
        template:`<div><span style="background-color:red;" ng-click="toggleText()">{{mytitle}}</span><div ng-transclude ng-show="showText"></div></div>`,
        require:true,
        replace:true,
        transclude:true,
        //將etitle屬性繫結到父控制器的scope域中
        scope:{
            mytitle:`=etitle`
        },
        link: function(scope,element,attr,accordionCtrl){
            scope.showText = false;
            scope.toggleText = function(){
                scope.showText = ! scope.showText;
            }
        }
    }
});
app.controller(`directive`,function($scope){
    $scope.title = "angular 學習";
    $scope.text = "angular js概念多";
});

expander指令中的link引數中增加了showText的值和toggleText的點選函式。

最後,再看一個多個摺疊皮膚的例子

<!DOCTYPE html>
<html ng-app="directive">
<head lang="en">
    <meta charset="UTF-8">
    <title>directive</title>
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="./directive.js"></script>
</head>
<body>
    <div ng-controller="directive">
        <accordion>
            <expander ng-repeat="expander in expanders" etitle="expander.title">{{expander.text}}</expander>
        </accordion>
    </div>
</body>
</html>

ng-repeat便利expanders的所有元素

var app = angular.module(`directive`,[]);
app.directive(`expander`,function(){
    return {
        restrict:`E`,
        template:`<div><span style="background-color:red;" ng-click="toggleText()">{{mytitle}}</span><div ng-transclude ng-show="showText"></div></div>`,
        require:`^?accordion`,
        replace:true,
        transclude:true,
        //將etitle屬性繫結到父控制器的scope域中
        scope:{
            mytitle:`=etitle`
        },
        link: function(scope,element,attr,accordionCtrl){
            scope.showText = false;
            accordionCtrl.addExpander(scope);
            scope.toggleText = function(){
                scope.showText = ! scope.showText;
                accordionCtrl.getOpened(scope);
            }
        }
    }
});
app.controller(`directive`,function($scope){
    $scope.expanders = [
        {title:"angular",text:"angular js概念多"},
        {title:"react",text:"react + reduce + ui路由機制"}
    ];
});

app.directive(`accordion`,function(){
   return {
       restrict:"E",
       template:`<div ng-transclude></div>`,
       replace:true,
       transclude:true,
       controller:function(){
           var expanders = [];

           this.getOpened = function(selectExpander){
               angular.forEach(expanders,function(e){
                    if (selectExpander != e){
                        e.showText = false;
                    }
               });
           }

           this.addExpander = function(e){
               expanders.push(e);
           }
       }
   }
});

demo原始碼地址

相關文章