首頁 >CMS教程 >&#&按 >使用 AngularJS 指令增強 HTML

使用 AngularJS 指令增強 HTML

王林
王林原創
2023-08-27 08:01:15738瀏覽

使用 AngularJS 指令增强 HTML

AngularJS 的主要特點是它允許我們擴展 HTML 的功能來服務於當今動態網頁的目的。在本文中,我將向您展示如何使用 AngularJS 的指令來使您的開發更快、更輕鬆,並且使您的程式碼更易於維護。

準備

第 1 步:HTML 範本

為了讓事情變得更簡單,我們將把所有程式碼寫在一個 HTML 檔案中。建立它並將基本的 HTML 模板放入其中:

<!DOCTYPE html> <html> <head> </head> <body> </body> </html>

現在將來自 Google CDN 的 angular.min.js 檔案加入到文件的 中:

 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>

第 2 步:建立模組

現在讓我們為指令建立模組。我將其稱為 example,但您可以選擇任何您想要的名稱,只需記住我們將使用此名稱作為稍後創建的指令的命名空間。

將此程式碼放在 底部的腳本標記中:

var module = angular.module('example', []);

我們沒有任何依賴項,因此angular.module() 的第二個參數中的數組為空,但不要完全刪除它,否則您將得到$injector:nomod錯誤,因為angular.module() 的單參數形式會擷取已存在模組的引用,而不是建立新模組。

您還必須將 ng-app="example" 屬性新增至 標記才能使應用程式正常運作。之後文件應如下所示:

<!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>

屬性指令:1337 C0NV3R73R

首先,我們將創建一個簡單的指令,其工作方式與 ngBind 類似,但它將把文字更改為 leet talk。

第 1 步:指令宣告

使用 module.directive() 方法宣告指令:

module.directive('exampleBindLeet', function () {

第一個參數是指令的名稱。它必須採用駝峰式命名法,但由於 HTML 不區分大小寫,因此您將在 HTML 程式碼中使用破折號分隔的小寫形式 (example-bind-leet)。

作為第二個參數傳遞的函數必須傳回一個描述該指令的物件。目前它只有一個屬性:連結函數:

    return {
		link: link
	};
});

第2步:連結函數

您可以在 return 語句之前定義函數,也可以直接在傳回的物件中定義函數。它用於操作我們的指令所應用的元素的 DOM,並使用三個參數進行呼叫:

function link($scope, $elem, attrs) {

$scope 是一個Angular 範圍對象,$elem 是該指令匹配的DOM 元素(它包裝在jqLit​​​​e 中,jqLit​​​​e 是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></script> 標記的頂部。正如您所看到的,這是最基本的 leet 轉換器,因為它只會取代十個字元。

之後,我們將字串轉換為 leet say,我們使用 jqLit​​e 的 text() 方法將其放入該指令匹配的元素的內部文字中。

現在您可以透過將此 HTML 程式碼放入文件的 中來測試它:

<div example-bind-leet="This text will be converted to leet speak!"></div>

輸出應如下所示:

但這並不完全是 ngBind 指令的工作原理。我們將在接下來的步驟中改變這一點。

第 3 步:範圍

首先,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 或创建一个控制器,并将 divexample-bind-leet 属性的值更改为您使用的变量的名称:

 <body ng-app="example" ng-init="textToConvert = 'This text will be converted to leet speak!'"> 
    <div example-bind-leet="textToConvert"></div> 
</body> 

第 4 步:检测更改

但这仍然不是 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></example-progress>

第 1 步:样式

为了让我们的进度条看起来像一个进度条,我们必须使用一些 CSS。将此代码放入文档的 中的 <style></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:relativeposition:absolute 的组合来定位绿色条和 <example-progress></example-progress> 元素。

第 2 步:指令的属性

与前一个相比,这个需要更多的选项。看一下这段代码(并将其插入到您的 <script></script> 标记中):

module.directive('exampleProgress', function () {
    return {
		restrict: 'E',
		scope: {
			value: '=',
			max: '='
		},
		template: '',
		link: link
	};
});

正如您所看到的,我们仍然使用范围(这次有两个属性 - value 表示当前值,max 表示最大值)和 link() 函数,但有两个新属性:

  • restrict: 'E' - 这告诉编译器查找元素而不是属性。可能的值为:
    • 'A' - 仅匹配属性名称(这是默认行为,因此如果您只想匹配属性,则无需设置它)
    • 'E' - 仅匹配元素名称
    • 'C' - 仅匹配类名
  • 您可以将它们组合起来,例如“AEC”将匹配属性、元素和类名称。
  • template: '' - 这允许我们更改元素的内部 HTML(如果您想从单独的文件加载 HTML,还有 templateUrl)

当然,我们不会将模板留空。将此 HTML 放在那里:

<div class="progressBar"></div><div class="progressValue">{{ percentValue }}%</div>

如您所见,我们还可以在模板中使用 Angluar 表达式 - percentValue 将从指令的范围中获取。

第3步:链接函数

该函数与上一个指令中的函数类似。首先,创建一个将执行指令逻辑的本地函数 - 在本例中更新 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 的宽度,因为 jqLit​​e 不支持 .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> 元素:

<example-progress value="progressValue" max="progressMax"></example-progress>

现在应该如下所示:

<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> 

这就是结果:

第 4 步:使用 jQuery 添加动画

如果您为 progressValueprogressMax 添加输入,如下所示:

<input ng-model="progressValue"> 
<input ng-model="progressMax">

您会注意到,当您更改任何值时,宽度会立即发生变化。为了让它看起来更好一点,让我们使用 jQuery 来制作它的动画。将 jQuery 与 AngularJS 结合使用的好处是,当您包含 jQuery 的 <script></script> 时,Angular 会自动用它替换 jqLit​​e,使 $elem 成为 jQuery 对象。

因此,让我们首先将 jQuery 脚本添加到文档的 中,位于 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 文档的一些链接:

  • 开发者指南:指令
  • 综合指令 API
  • jqLit​​e(angular.element)API

以上是使用 AngularJS 指令增強 HTML的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn