小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

《AngularJS》5個實例詳解Directive(指令)機制

 KILLKISS 2014-02-10

《AngularJS》5個實例詳解Directive(指令)機制

 

大漠窮秋

 

本文整理并擴展了《AngularJS》這本書第六章里面的內(nèi)容,此書近期即將由電子工業(yè)出版社出版,敬請期待口令:Angular

 

1.一點小說明

 

指令的作用:實現(xiàn)語義化標簽

 

我們常用的HTML標簽是這樣的:

 

<div>
    <span>一點點內(nèi)容</span>
</div>

 

而使用AngularJS的directive(指令)機制,我們可以實現(xiàn)這樣的東西:

 

<tabpanel>
    <panel>子面板1</panel>
    <panel>子面板2</panel>
</tabpanel>

 

很多人可能要驚呼,這貨和JSP或者Struts等等框架里面的taglib很像啊!

 

呃,說實話,實際上就是這樣的,只不過這里是使用JavaScript來實現(xiàn)的。正因為如此,所以很多taglib做不到的功能,使用它就都可以做到,比如訪問N層scope里面的對象之類的事情(參見后面第5個例子)。

 

2.實例1:從最簡單的開始

 

<html ng-app='app'>
    <body>
        <hello></hello>
    </body>

    <script src="../angular-1.0.3/angular.min.js"></script>
    <script src="HelloDirect.js"></script>
</html>

 

對于以上代碼里面的<hello>標簽,瀏覽器顯然是不認識的,它唯一能做的事情就是無視這個標簽。那么,為了讓瀏覽器能夠認識這個標簽,我們需要使用Angular來定義一個hello指令(本質(zhì)上說就是自己來把<hello>這種玩意兒替換成瀏覽器能識別的那些標準HTML標簽)。

 

來看這段溫馨的JS代碼:

 

var appModule = angular.module('app', []);
appModule.directive('hello', function() {
    return {
        restrict: 'E',
        template: '<div>Hi there</div>',
        replace: true
    };
});

 

以上代碼大概看兩眼就可以了,不要太在意細節(jié)。

 

然后我們就可以在瀏覽器里面看到這樣的內(nèi)容:

 



 

 

實際產(chǎn)生的標簽結(jié)構(gòu)是這樣的:

 



 

 

可以看到,<hello>這個東東已經(jīng)被<div>Hi there</div>這個標簽替換掉了,這也是以上JS代碼里面replace:true這行配置的作用,代碼里面的template配置 項當然就是我們要的div標簽啦,至于restrict:'E'這個配置項的含義,請看下表:

 



 

 

ok,看完上面的表格,對于restrict這個屬性相信你已經(jīng)秒懂了,那么我們來玩兒點花樣吧。如果我們需要替換的HTML標簽很長,顯然不能用 拼接字符串的方式來寫,這時候我們可以用templateUrl來替代template,從而可以把模板寫到一個獨立的HTML文件中。

 

3.實例2:transclude(變換)

 

先看例子,JS代碼:

 

var appModule = angular.module('app', []);
    appModule.directive('hello', function() {
    return {
        restrict: 'E',
        template: '<div>Hi there <span ng-transclude></span></div>',
        transclude: true
    };
});

 

HTML代碼:

 

<html ng-app='app'>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    </head>
    <body>
        <hello>
            <br/>
            <span>原始的內(nèi)容,</span><br/>
            <span>還會在這里。</span>
        </hello>
        <hello>
        </hello>
    </body>

    <script src="../angular-1.0.3/angular.min.js"></script>
    <script src="Transclude.js"></script>
</html>

 

運行效果如下:

 



 

 

生成的HTML標簽結(jié)構(gòu)如下:

 



 

 

和第一個例子對比,這個例子的JS和HTML代碼都略有不同,JS代碼里面多了一個transclude: true,HTML代碼里面在<hello>內(nèi)部出現(xiàn)了子標簽。

 

按照我們在第一個例子中的說法,指令的作用是把我們自定義的語義化標簽替換成瀏覽器能夠認識的HTML標簽。那好,如果我們自定義的標簽內(nèi)部出現(xiàn)了子標簽,應該如何去處理呢?很顯然,transclude就是用來處理這種情況的。

 

對于當前這個例子,transclude的作用可以簡化地理解成:把<hello>標簽替換成我們所編寫的HTML模板,但是<hello>標簽內(nèi)部的內(nèi)容保持不變。

 

很顯然,由于我們沒有加replace:true選項,所以<hello>標簽還在,沒有被替換掉。同時,通過這個例子你還還會發(fā)現(xiàn)一 個暗藏的屬性,那就是瀏覽器實際上非常智能,雖然它并不認識<hello>這個標簽,但是頁面沒有出錯,它只是默默地把這個標簽忽略掉了!怎 么樣?是不是碉堡了?

 

你可以自己在上面的JS代碼里面加上replace:true,然后再看生成的HTML結(jié)構(gòu)。

 

4.實例3:關(guān)于compile和link

 

JS代碼:

 

var appModule = angular.module('app', []);
appModule.directive('hello', function() {
    return {
        restrict: 'E',
        template: '<span>Hi there</span>',
        replace: true
    };
});
appModule.controller('MyController',function($scope) {
    $scope.things = [1,2,3,4,5,6];
});

 

HTML代碼:

 

<html ng-app='app'>
    <body ng-controller='MyController'>
        <div ng-repeat='thing in things'>
            {{thing}}.<hello></hello>
        </div>
    </body>

    <script src="../angular-1.0.3/angular.min.js"></script>
    <script src="CompileAndLink.js"></script>
</html>

 

呃,這個例子是用來解釋一點點理論的,所以單純看效果可能看不出個鳥。

 

如前所述,指令的本質(zhì)其實是一個替換過程。好,既然如此,Angular到底是如何進行替換的呢?嗯嗯,這個過程分2個階段,也就是本節(jié)標題所說的compile(編譯)和link(連接)了。

 

簡而言之,compile階段進行標簽解析和變換,link階段進行數(shù)據(jù)綁定等操作。這里面更加細節(jié)的處理過程請參見《AngularJS》這本書中的解析,這里就不贅述了(呃,實際上是因為解釋起來很長很麻煩,叔懶得在這兒說了

 )。

 

那么,知道這件事情有什么用途呢?

 

比方說,你有一些事件需要綁定到某個元素上,那么你需要提供一個link函數(shù),做法請看下一個例子。

 

5.實例4:一個復雜一點的例子Expander

 

這是《AngularJS》這本書里面提供的一個例子,但是書里面沒有給出完整的可運行代碼,所以這里給出來,大家參考一下。

 

JS代碼:

 

var expanderModule=angular.module('expanderModule', [])
expanderModule.directive('expander', function() {
    return {
        restrict : 'EA',
        replace : true,
        transclude : true,
        scope : {
            title : '=expanderTitle'
        },
        template : '<div>'
                 + '<div class="title" ng-click="toggle()">{{title}}</div>'
                 + '<div class="body" ng-show="showMe" ng-transclude></div>'
                 + '</div>',
        link : function(scope, element, attrs) {
            scope.showMe = false;
            scope.toggle = function toggle() {
                scope.showMe = !scope.showMe;
            }
        }
    }
});
expanderModule.controller('SomeController',function($scope) {
    $scope.title = '點擊展開';
    $scope.text = '這里是內(nèi)部的內(nèi)容。';
});

 

HTML代碼:

 

<html ng-app='expanderModule'>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script src="../angular-1.0.3/angular.min.js"></script>
        <link rel="stylesheet" type="text/css" href="ExpanderSimple.css"/>
    </head>
    <body>
        <div ng-controller='SomeController'>
            <expander class='expander' expander-title='title'>
                {{text}}
            </expander>
        </div>
    </body>
    <script src="ExpanderSimple.js"></script>
</html>

 

CSS代碼:

 

.expander {
    border: 1px solid black;
    width: 250px;
}

.expander>.title {
    background-color: black;
    color: white;
    padding: .1em .3em;
    cursor: pointer;
}

.expander>.body {
    padding: .1em .3em;
}

 

運行效果如下:

 



 

 

注意一下JS代碼里面的這一段:

 

link : function(scope, element, attrs) {
    scope.showMe = false;
    scope.toggle = function toggle() {
        scope.showMe = !scope.showMe;
    }
}

 

自己跑一跑例子,研究一番,不多解釋。

 

6.實例5:一個綜合的例子

 

JS代碼:

 

var expModule=angular.module('expanderModule',[])
expModule.directive('accordion', function() {
    return {
        restrict : 'EA',
        replace : true,
        transclude : true,
        template : '<div ng-transclude></div>',
        controller : function() {
            var expanders = [];
            this.gotOpened = function(selectedExpander) {
                angular.forEach(expanders, function(expander) {
                    if (selectedExpander != expander) {
                        expander.showMe = false;
                    }
                });
            }
            this.addExpander = function(expander) {
                expanders.push(expander);
            }
        }
    }
});

expModule.directive('expander', function() {
    return {
        restrict : 'EA',
        replace : true,
        transclude : true,
        require : '^?accordion',
        scope : {
            title : '=expanderTitle'
        },
        template : '<div>'
                   + '<div class="title" ng-click="toggle()">{{title}}</div>'
                   + '<div class="body" ng-show="showMe" ng-transclude></div>'
                   + '</div>',
        link : function(scope, element, attrs, accordionController) {
            scope.showMe = false;
            accordionController.addExpander(scope);
            scope.toggle = function toggle() {
                scope.showMe = !scope.showMe;
                accordionController.gotOpened(scope);
            }
        }
    }
});

expModule.controller("SomeController",function($scope) {
    $scope.expanders = [{
        title : 'Click me to expand',
        text : 'Hi there folks, I am the content that was hidden but is now shown.'
    }, {
        title : 'Click this',
        text : 'I am even better text than you have seen previously'
    }, {
        title : 'Test',
        text : 'test'
    }];
});

 

HTML代碼:

 

<html ng-app="expanderModule">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script src="../angular-1.0.3/angular.min.js"></script>
        <link rel="stylesheet" type="text/css" href="Accordion.css"/>
    </head>
    <body ng-controller='SomeController' >
        <accordion>
            <expander class='expander' ng-repeat='expander in expanders' expander-title='expander.title'>
                {{expander.text}}
            </expander>
        </accordion>
    </body>
    <script src="Accordion.js"></script>
</html>

 

CSS代碼:

 

.expander {
    border: 1px solid black;
    width: 250px;
}

.expander>.title {
    background-color: black;
    color: white;
    padding: .1em .3em;
    cursor: pointer;
}

.expander>.body {
    padding: .1em .3em;
}

 

運行效果:

 



 

 

這個例子主要的難點在于如何在子Expander里面訪問外層Accordion的scope中的數(shù)據(jù),這一點解釋起來略復雜,這里就不展開了,詳細描述參見《AngularJS》一書 

 

 

AngularJS官方站點在這里:http:///

 

[全文完]

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多