2015年8月4日

自訂AngularJS Directives(一)

AngularJS

AngularJS是當前知名的JavaScript框架,其主要理念是透過MVC(Model-View-Controller)架構來幫助Web App開發者建置網站。

Directives

在AngularJS中,Directives指的是其自行定義的DOM元件,屬性,class名稱...等。曾接觸過AngularJS的讀者,一定對ng-controllerng-bindng-model, ng-repeat...等等名詞不陌生,這些都是AngularJS內建的Directives。

AngularJS透過Directives賦與DOM元件額外的能力,如:ng-bind可以自動將某個記憶體中的變數與HTML元件建立關連;當該變數內容異動時,相關連的HTML元件的內容也將自動更新。

此外,AngularJS允許網頁開發者自訂Directives,這也是本篇文章將要探討的主題。

自訂Directives為AngularJS中稍微進階的議題。未曾接觸過AngularJS的讀者們,建議可以先參考幾篇AngularJS的基本介紹:

AngularJS官方文件

前端工程的極致精品: AngularJS 開發框架介紹

AngularJS 入門簡介(slideshare)

對於AngularJS的基本概念,本篇文章將暫不贅述。

為何需要自訂Directives

筆者前陣子開始研究AngularJS,並試著思考:已往曾經寫過的網頁,倘若是使用AngularJS食,該如何撰寫。

然而,卻遇到了一些瓶頸。如:我需要把我的網頁切成多個子頁面,並將每個子頁面的HTML/JavaScript獨立出來,並視情況顯示某些子頁面,或是移除某些子頁面。最重要的-這些子頁面可能需要可以被重複使用。

後來看了各大論壇的討論,以及幾篇部落格文章,都介紹到了AngularJS的自訂Directives功能,如:
SushiWen's Blog: 比較Backbone.js, Angular.js, Ember.js, Knockout.js 心得

AngularJS的自訂Directives功能,概念上接近允許使用者自訂一個DOM元件。
您若已經非常熟悉AngularJS,亦可參考AngularJS官方對自訂Directives功能的介紹:Creating Custom Directives

本文僅從最簡單的範例開始介紹。

自訂Directives範例一:Hello World

以下範例自訂了一個helloWorld directive。

<!doctype html>
<html lang="en" ng-app="myapp">
<head>
  <meta charset="utf-8">
  <title>My HTML File</title>
  <script src="angular.js"></script>
  <script>
    angular.module('myapp', [])
    .directive('helloWorld', function() {
        return {
            restrict: 'AE',                
            template: '<h3>Hello World!!</h3>',
            replace: true,
        };
    });
  </script>
</head>
<body>    
    <hello-world></hello-world>
</body>
</html>

結果呈現了簡單的:

Hello World!!

若使用瀏覽器的開發工具檢視DOM元件,可以看到:

<body>    
    <h3>Hello World!!</h3>
</body>

Directive名稱

以上範例在HTML中,寫的是hello-world;而AngularJS會自動將其轉換為helloWorld

Directive名稱的轉換規則如下:

1.去掉元素/屬性名稱前面的x-以及data-

2.將冒號( : ), 連字號( - )或底線( _ )作為分隔符號,將元素/屬性名稱轉為駝峰式大小寫(camelCase)格式。

如以下寫法都會符合helloWorld directive:

<hello-world></hello-world> <br/>
<hello:world></hello:world> <br/>
<hello_world></hello_world> <br/>
<data-hello-world></data-hello-world> <br/>
<x-hello-world></x-hello-world> <br/>

restrict參數

restrict參數表示此Directive允許以何種方式呈現。

A表示屬性:

<div hello-world></div>

E表示元素:

<hello-world></hello-world>

C表示類別:

<div class="hello-world"></div>

A, E, C參數可以混合使用。如範例中使用'AE',表示以下兩種寫法都會被接受:

<div hello-world></div>
<hello-world></hello-world>

template/templateURL參數

template參數表示此Directive實際上呈現的HTML內容,
如上例中:

<h3>Hello World!!</h3>

此外,若HTML內容比較龐大時,可以改將其放在一個檔案中,
並使用templateURL參數

因此上例可改成:

  <script>
    angular.module('myapp', [])
    .directive('helloWorld', function() {
        return {
            restrict: 'AE',                
            templateURL: 'helloWorldTemplate.html',
            replace: true,
        };
    });
  </script>

helloWorldTemplate.html內容如下:

<h3>Hello World!!</h3>

replace參數

replace參數表示原本的DOM元素是否需要被取代。

在上例中,replace為true,因此在使用瀏覽器的開發工具檢視DOM元件,只會看到:

<body>    
    <h3>Hello World!!</h3>
</body>

若replace為false時,則會看到:

<body>    
    <hello-world>
        <h3>Hello World!!</h3>
    </hello-world>
</body>

需特別注意的是,replace參數在AngularJS 1.3之後已不被建議使用,並可能在未來的版本被移除;因此可能的話,請避免使用replace參數。

小結

上述內容僅讓讀者對AngularJS的自訂Directives有了最基礎的概念;而下一篇將進一步介紹如何為自訂Directives建立其專屬的函式/API, 發揮其真正強大的功能, 以建立可重用的web元件。