AngularJS 的主要特點是它允許我們擴展 HTML 的功能來服務於當今動態網頁的目的。在本文中,我將向您展示如何使用 AngularJS 的指令來使您的開發更快、更輕鬆,並且使您的程式碼更易於維護。
為了讓事情變得更簡單,我們將把所有程式碼寫在一個 HTML 檔案中。建立它並將基本的 HTML 模板放入其中:
<!DOCTYPE html> <html> <head> </head> <body> </body> </html>
現在將來自 Google CDN 的 angular.min.js
檔案加入到文件的 <head>
中:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
現在讓我們為指令建立模組。我將其稱為 example,但您可以選擇任何您想要的名稱,只需記住我們將使用此名稱作為稍後創建的指令的命名空間。
將此程式碼放在 <head>
底部的腳本標記中:
var module = angular.module('example', []);
我們沒有任何依賴項,因此angular.module()
的第二個參數中的數組為空,但不要完全刪除它,否則您將得到$injector:nomod錯誤,因為angular.module()
的單參數形式會擷取已存在模組的引用,而不是建立新模組。
您還必須將 ng-app="example"
屬性新增至 <body>
標記才能使應用程式正常運作。之後文件應如下所示:
<!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script> <script> var module = angular.module('example', []); </script> </head> <body ng-app="example"> </body> </html>
首先,我們將創建一個簡單的指令,其工作方式與 ngBind 類似,但它將把文字更改為 leet talk。
使用 module.directive()
方法宣告指令:
module.directive('exampleBindLeet', function () {
第一個參數是指令的名稱。它必須採用駝峰式命名法,但由於 HTML 不區分大小寫,因此您將在 HTML 程式碼中使用破折號分隔的小寫形式 (example-bind-leet)。
作為第二個參數傳遞的函數必須傳回一個描述該指令的物件。目前它只有一個屬性:連結函數:
return { link: link }; });
您可以在 return 語句之前定義函數,也可以直接在傳回的物件中定義函數。它用於操作我們的指令所應用的元素的 DOM,並使用三個參數進行呼叫:
function link($scope, $elem, attrs) {
$scope
是一個Angular 範圍對象,$elem
是該指令匹配的DOM 元素(它包裝在jqLite 中,jqLite 是AngularJS 的jQuery最常用函數的子集) attrs
是一個具有所有元素屬性的物件(具有規範化名稱,因此example-bind-leet 將可用作attrs.exampleBindLeet
)。
我們的指令中此函數的最簡單的程式碼如下所示:
var leetText = attrs.exampleBindLeet.replace(/[abegilostz]/gmi, function (letter) { return leet[letter.toLowerCase()]; }); $elem.text(leetText); }
首先,我們將 example-bind-leet
屬性中提供的文字中的一些字母替換為 leet 表中的替換內容。該表如下所示:
var leet = { a: '4', b: '8', e: '3', g: '6', i: '!', l: '1', o: '0', s: '5', t: '7', z: '2' };
您應該將其放在 <script>
標記的頂部。正如您所看到的,這是最基本的 leet 轉換器,因為它只會取代十個字元。
之後,我們將字串轉換為 leet say,我們使用 jqLite 的 text()
方法將其放入該指令匹配的元素的內部文字中。
現在您可以透過將此 HTML 程式碼放入文件的 <body>
中來測試它:
<div example-bind-leet="This text will be converted to leet speak!"></div>
輸出應如下所示:
但這並不完全是 ngBind
指令的工作原理。我們將在接下來的步驟中改變這一點。
首先,example-bind-leet
屬性中傳遞的應該是對目前作用域中變數的引用,而不是我們要轉換的文字。為此,我們必須為指令建立一個隔離的範圍。
我們可以透過將作用域物件加入指令函數的傳回值來實現這一點:
module.directive('exampleBindLeet', function () { ... return { link: link, scope: { } }; );
該物件中的每個屬性都將在指令的範圍內可用。它的值將由這裡的值決定。如果我們使用“-”,則該值將等於與屬性同名的屬性的值。使用“=”將告訴編譯器我們期望傳遞當前作用域中的變數 - 這將像 ngBind
:
scope: { exampleBindLeet: '=' }
您也可以使用任何內容作為屬性名稱,並將規範化(轉換為駝峰命名法)的屬性名稱放在 - 或 = 後面:
scope: { text: '=exampleBindLeet' }
選擇最適合您的。現在我們還必須更改連結函數以使用 $scope
而不是 attr
:
function link($scope, $elem, attrs) { var leetText = $scope.exampleBindLeet.replace(/[abegilostz]/gmi, function (letter) { return leet[letter.toLowerCase()]; }); $elem.text(leetText); }
现在使用 ngInit 或创建一个控制器,并将 div
的 example-bind-leet
属性的值更改为您使用的变量的名称:
<body ng-app="example" ng-init="textToConvert = 'This text will be converted to leet speak!'"> <div example-bind-leet="textToConvert"></div> </body>
但这仍然不是 ngBind
的工作原理。要查看我们添加一个输入字段以在页面加载后更改 textToConvert 的值:
<input ng-model="textToConvert">
现在,如果您打开页面并尝试更改输入中的文本,您将看到我们的 div
中没有任何变化。这是因为 link()
函数在编译时每个指令都会调用一次,因此它无法在每次范围内发生更改时更改元素的内容。
要改变这一点,我们将使用 $scope.$watch() 方法。它接受两个参数:第一个是 Angular 表达式,每次修改范围时都会对其进行求值,第二个是回调函数,当表达式的值发生更改时将被调用。
首先,让我们将 link()
函数中的代码放入其中的本地函数中:
function link($scope, $elem, attrs) { function convertText() { var leetText = $scope.exampleBindLeet.replace(/[abegilostz]/gmi, function (letter) { return leet[letter.toLowerCase()]; }); $elem.text(leetText); } }
现在,在该函数之后,我们将调用 $scope.$watch()
,如下所示:
$scope.$watch('exampleBindLeet', convertLeet);
如果您现在打开页面并更改输入字段中的某些内容,您将看到 div
的内容也按预期发生了变化。
现在我们将编写一个指令来为我们创建一个进度条。为此,我们将使用一个新元素:<example-progress>
。
为了让我们的进度条看起来像一个进度条,我们必须使用一些 CSS。将此代码放入文档的 <head>
中的 <style>
元素中:
example-progress { display: block; width: 100%; position: relative; border: 1px solid black; height: 18px; } example-progress .progressBar { position: absolute; top: 0; left: 0; bottom: 0; background: green; } example-progress .progressValue { position: absolute; top: 0; left: 0; right: 0; bottom: 0; text-align: center; }
正如你所看到的,它非常基本 - 我们使用 position:relative
和 position:absolute
的组合来定位绿色条和 <example-progress>
元素。
与前一个相比,这个需要更多的选项。看一下这段代码(并将其插入到您的 <script>
标记中):
module.directive('exampleProgress', function () { return { restrict: 'E', scope: { value: '=', max: '=' }, template: '', link: link }; });
正如您所看到的,我们仍然使用范围(这次有两个属性 - value 表示当前值,max 表示最大值)和 link() 函数,但有两个新属性:
当然,我们不会将模板留空。将此 HTML 放在那里:
<div class="progressBar"></div><div class="progressValue">{{ percentValue }}%</div>
如您所见,我们还可以在模板中使用 Angluar 表达式 - percentValue
将从指令的范围中获取。
该函数与上一个指令中的函数类似。首先,创建一个将执行指令逻辑的本地函数 - 在本例中更新 percentValue
并设置 div.progressBar
的宽度:
function link($scope, $elem, attrs) { function updateProgress() { var percentValue = Math.round($scope.value / $scope.max * 100); $scope.percentValue = Math.min(Math.max(percentValue, 0), 100); $elem.children()[0].style.width = $scope.percentValue + '%'; } }
正如你所看到的,我们不能使用 .css()
来更改 div.progressBar 的宽度,因为 jqLite 不支持 .children( )
。我们还需要使用 Math.min()
和 Math.max()
将值保持在 0% 到 100% 之间 - 如果 precentValue 小于 0,则 Math.max()
将返回 0;如果 percentValue
大于 100,则 Math.min() 将返回 100。
现在不再是两个 $scope.$watch()
调用(我们必须注意 $scope.value
和 中的变化$scope.max
) 让我们使用 $scope.$watchCollection()
,它类似,但适用于属性集合:
$scope.$watchCollection('[value, max]', updateProgress);
请注意,我们传递的第一个参数看起来像数组,而不是 JavaScript 的数组。
要了解它是如何工作的,首先更改 ngInit
以初始化另外两个变量:
<body ng-app="example" ng-init="textToConvert = 'This text will be converted to leet speak!'; progressValue = 20; progressMax = 100">
然后在我们之前使用的 div
下面添加 <example-progress>
元素:
<example-progress value="progressValue" max="progressMax"></example-progress>
<body>
现在应该如下所示:
<body ng-app="example" ng-init="textToConvert = 'This text will be converted to leet speak!'; progressValue = 20; progressMax = 100"> <div example-bind-leet="textToConvert"></div> <example-progress value="progressValue" max="progressMax"></example-progress> </body>
这就是结果:
如果您为 progressValue
和 progressMax
添加输入,如下所示:
<input ng-model="progressValue"> <input ng-model="progressMax">
您会注意到,当您更改任何值时,宽度会立即发生变化。为了让它看起来更好一点,让我们使用 jQuery 来制作它的动画。将 jQuery 与 AngularJS 结合使用的好处是,当您包含 jQuery 的 <script>
时,Angular 会自动用它替换 jqLite,使 $elem
成为 jQuery 对象。
因此,让我们首先将 jQuery 脚本添加到文档的 <head>
中,位于 AngularJS 之前:
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
现在我们可以更改 updateProgress()
函数以使用 jQuery 的 .animate()
方法。更改此行:
$elem.children()[0].style.width = $scope.percentValue + '%';
对此:
$elem.children('.progressBar').stop(true, true).animate({ width: $scope.percentValue + '%' });
并且您应该有一个精美的动画进度条。我们必须使用 .stop() 方法来停止并完成任何待处理的动画,以防我们在动画进行过程中更改任何值(尝试删除它并快速更改输入中的值以了解为什么需要它)。 p>
当然,您应该更改 CSS,并可能在应用程序中使用其他一些缓动函数来匹配您的风格。
AngularJS 的指令对于任何 Web 开发人员来说都是一个强大的工具。您可以创建一组自己的指令来简化和促进您的开发过程。您可以创建的内容仅受您的想象力限制,您几乎可以将所有服务器端模板转换为 AngularJS 指令。
以下是 AngularJS 文档的一些链接:
以上是使用 AngularJS 指令增強 HTML的詳細內容。更多資訊請關注PHP中文網其他相關文章!