您好,欢迎访问一九零五行业门户网

使用 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'};
您应该将其放在 标记的顶部。正如您所看到的,这是最基本的 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 或创建一个控制器,并将 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>
第 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 的内容也按预期发生了变化。
元素指令:进度条现在我们将编写一个指令来为我们创建一个进度条。为此,我们将使用一个新元素:。
第 1 步:样式为了让我们的进度条看起来像一个进度条,我们必须使用一些 css。将此代码放入文档的 中的 元素中:
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 的组合来定位绿色条和 元素。
第 2 步:指令的属性与前一个相比,这个需要更多的选项。看一下这段代码(并将其插入到您的 标记中):
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 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 添加动画如果您为 progressvalue 和 progressmax 添加输入,如下所示:
<input ng-model=progressvalue> <input ng-model=progressmax>
您会注意到,当您更改任何值时,宽度会立即发生变化。为了让它看起来更好一点,让我们使用 jquery 来制作它的动画。将 jquery 与 angularjs 结合使用的好处是,当您包含 jquery 的 时,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 文档的一些链接:
开发者指南:指令综合指令 apijqlit​​e(angular.element)api以上就是使用 angularjs 指令增强 html的详细内容。
其它类似信息

推荐信息