Maison > Article > Tutoriel CMS > Améliorez le HTML avec les directives AngularJS
La principale caractéristique d'AngularJS est qu'il nous permet d'étendre les fonctionnalités du HTML pour répondre aux besoins des pages Web dynamiques d'aujourd'hui. Dans cet article, je vais vous montrer comment utiliser les directives d'AngularJS pour rendre votre développement plus rapide et plus facile, et rendre votre code plus maintenable.
Pour faciliter les choses, nous écrirons tout le code dans un seul fichier HTML. Créez-le et insérez-y un modèle HTML de base :
<!DOCTYPE html> <html> <head> </head> <body> </body> </html>
proviendra désormais de Google CDN angular.min.js
文件添加到文档的 en :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
Créons maintenant le module pour la directive. Je l'appellerai exemple, mais vous pouvez choisir le nom de votre choix, n'oubliez pas que nous l'utiliserons comme espace de noms pour la directive que nous créerons plus tard.
Mettez ce code dans une balise de script en bas de :
var module = angular.module('example', []);
Nous n'avons aucune dépendance, donc la forme à argument unique de angular.module()
的第二个参数中的数组为空,但不要完全删除它,否则您将得到 $injector:nomod错误,因为 angular.module()
récupère une référence à un module déjà existant plutôt que de créer un nouveau module.
Vous devez également le marquer avec ng-app="example"
属性添加到 pour que l'application fonctionne correctement. Le fichier devrait alors ressembler à ceci :
<!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>
Tout d'abord, nous allons créer une directive simple qui fonctionnera de la même manière que ngBind, mais elle changera le texte en leet talk.
Déclarez les directives en utilisant la méthode module.directive()
:
module.directive('exampleBindLeet', function () {
Le premier paramètre est le nom de la commande. Il doit être en camelCase, mais comme HTML n'est pas sensible à la casse, vous utiliserez des minuscules délimitées par des tirets (exemple-bind-leet) dans le code HTML.
La fonction passée en deuxième argument doit renvoyer un objet décrivant l'instruction. Actuellement il n'a qu'un seul attribut : fonction de lien :
return { link: link }; });
Vous pouvez définir la fonction avant l'instruction return ou directement dans l'objet retourné. Il est utilisé pour manipuler le DOM de l'élément auquel notre directive s'applique, et est appelé avec trois arguments :
function link($scope, $elem, attrs) {
$scope
是一个 Angular 范围对象,$elem
是该指令匹配的 DOM 元素(它包装在 jqLite 中,jqLite 是 AngularJS 的 jQuery 最常用函数的子集) attrs
是一个具有所有元素属性的对象(具有规范化名称,因此 example-bind-leet 将可用作 attrs.exampleBindLeet
).
Le code le plus simple pour cette fonction dans notre directive ressemble à ceci :
var leetText = attrs.exampleBindLeet.replace(/[abegilostz]/gmi, function (letter) { return leet[letter.toLowerCase()]; }); $elem.text(leetText); }
Tout d'abord, nous remplaçons certaines lettres du texte fourni dans l'attribut example-bind-leet
par le contenu de remplacement de la table leet. Le tableau ressemble à ceci :
var leet = { a: '4', b: '8', e: '3', g: '6', i: '!', l: '1', o: '0', s: '5', t: '7', z: '2' };
Vous devez le placer au-dessus de la marque <script></script>
. Comme vous pouvez le constater, il s'agit du convertisseur leet le plus basique puisqu'il ne remplace que dix caractères.
Après cela, nous convertissons la chaîne en leet say, que nous utilisons la méthode text()
de jqLite pour insérer dans le texte interne de l'élément correspondant à cette directive.
Vous pouvez maintenant tester ce code HTML en le plaçant à l'intérieur du de votre document :
<div example-bind-leet="This text will be converted to leet speak!"></div>
Le résultat devrait ressembler à ceci :
Mais ce n’est pas exactement ainsi que fonctionne la directive ngBind
. Nous modifierons cela dans les prochaines étapes.
Tout d'abord, ce qui est transmis dans l'attribut example-bind-leet
doit être une référence à la variable dans la portée actuelle, et non au texte que nous voulons convertir. Pour ce faire, nous devons créer un champ d’application isolé pour la directive.
Nous pouvons y parvenir en ajoutant un objet scope à la valeur de retour de la fonction directive :
module.directive('exampleBindLeet', function () { ... return { link: link, scope: { } }; );
Chaque propriété de l'objet sera disponible dans le cadre de la directive. Sa valeur sera déterminée par la valeur ici. Si nous utilisons "-", la valeur sera égale à la valeur de l'attribut du même nom. L'utilisation de "=" indiquera au compilateur que nous prévoyons de transmettre des variables dans la portée actuelle - cela fonctionnera comme ngBind
:
scope: { exampleBindLeet: '=' }
Vous pouvez également utiliser n'importe quoi comme nom de propriété et mettre le nom de propriété normalisé (converti en camelCase) après - ou = :
scope: { text: '=exampleBindLeet' }
Choisissez celui qui vous convient le mieux. Maintenant, nous devons également changer la fonction de lien pour utiliser $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></example-progress>
。
为了让我们的进度条看起来像一个进度条,我们必须使用一些 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:relative
和 position:absolute
的组合来定位绿色条和 <example-progress></example-progress>
元素。
与前一个相比,这个需要更多的选项。看一下这段代码(并将其插入到您的 <script></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>
元素:
<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>
这就是结果:
如果您为 progressValue
和 progressMax
添加输入,如下所示:
<input ng-model="progressValue"> <input ng-model="progressMax">
您会注意到,当您更改任何值时,宽度会立即发生变化。为了让它看起来更好一点,让我们使用 jQuery 来制作它的动画。将 jQuery 与 AngularJS 结合使用的好处是,当您包含 jQuery 的 <script></script>
时,Angular 会自动用它替换 jqLite,使 $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 文档的一些链接:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!