AngularJS 中的自定义指令:如何创建?[示例]
什么是自定义指令?
A 自定义指令 AngularJS 中的自定义指令是用户自定义指令,允许用户使用所需的函数来扩展 HTML 功能。可以使用“directive”函数来定义它,并替换使用它的元素。尽管 AngularJS 有很多现成的强大指令,但有时需要自定义指令。
如何创建自定义指令?
让我们看一个如何创建 AngularJS 自定义指令的例子。
在我们的例子中,自定义指令只是在调用该指令时在我们的页面中注入一个包含文本“AngularJS 教程”的 div 标签。
<!DOCTYPE html> <html> <head> <meta chrset="UTF 8"> <title>Event Registration</title> </head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp"> <div ng-guru=""></div> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.directive('ngGuru',function(){ return { template: '<div>Angular JS Tutorial</div>' } }); </script> </body> </html>
代码说明
- 我们首先创建一个 模块 对于我们的 Angular 应用程序。这是创建自定义指令所必需的,因为该指令将使用此模块创建。
- 我们现在正在创建一个名为“ngGuru”的自定义指令,并定义一个包含我们的指令的自定义代码的函数。注: - 请注意,在定义指令时,我们将其定义为 ngGuru,字母“G”大写。当我们从 div 标签将其作为指令访问时,我们将其作为 ng-guru 访问。这就是 angular 理解应用程序中定义的自定义指令的方式。首先,自定义指令的名称应以字母“ng”开头。其次,只有在调用指令时才应提及连字符“-”。第三,定义指令时字母“ng”后面的第一个字母可以是小写或大写。
- 我们使用模板参数,这是 Angular 为自定义指令定义的参数。在此,我们定义,无论何时使用此指令,都只需使用模板的值并将其注入调用代码中。
- 现在,我们正在使用我们自定义创建的“ng-guru”指令。当我们这样做时,我们为模板定义的值“ Angular JS 教程”现在将被注入到这里。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
上面的输出清楚地表明,我们的自定义 ng-guru 指令(其中定义了用于显示自定义文本的模板)显示在浏览器中。
AngularJs 指令和范围
范围被定义为通过管理视图和控制器之间的数据将控制器绑定到视图的粘合剂。
创建自定义 AngularJs 指令时,它们默认将可以访问父控制器中的作用域对象。
这样,自定义指令就可以轻松利用传递给主控制器的数据。
让我们看一个 AngularJS 自定义指令示例,了解如何在自定义指令中使用父控制器的范围。
<!DOCTYPE html> <html> <head> <meta chrset="UTF 8"> <title>Event Registration</title> </head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp" ng-controller="DemoController"> <div ng-guru=""></div> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.controller('DemoController',function($scope) { $scope.tutorialName = "Angular JS"; }); app.directive('ngGuru',function(){ return { template: '<div>{{tutorialName}}</div>' } }); </script> </body> </html>
代码说明
- 我们首先创建一个名为“DemoController”的控制器。在其中,我们定义一个名为 tutorialName 的变量,并在一个语句中将其附加到范围对象 - $scope.tutorialName = “AngularJS”。
- 在我们的自定义指令中,我们可以使用表达式调用变量“tutorialName”。此变量是可访问的,因为它是在控制器“DemoController”中定义的,该控制器将成为此指令的父级。
- 我们在 div 标签中引用控制器,该标签将充当我们的父 div 标签。请注意,需要先完成此操作,以便我们的自定义指令可以访问 tutorialName 变量。
- 最后,我们只需将自定义指令“ng-guru”附加到我们的 div 标签即可。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
上面的输出清楚地表明我们的自定义指令“ng-guru”使用了父控制器中的作用域变量tutorialName。
使用带指令的控制器
Angular 提供了以下功能 直接从自定义指令访问控制器的成员变量 而不需要范围对象。
这有时是必要的,因为在应用程序中您可能有属于多个控制器的多个范围对象。
因此,您很有可能犯访问错误控制器的范围对象的错误。
在这种情况下,有一种方法可以从我的指令中特别提到“我想访问这个特定的控制器”。
让我们看一个例子来了解如何实现这一点。
<!DOCTYPE html> <html> <head> <meta chrset="UTF 8"> <title>Event Registration</title> </head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp" ng-controller="DemoController"> <div ng-guru99=""></div> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.controller('DemoController',function() { this.tutorialName = "Angular"; }); app.directive('ngGuru99',function(){ return { controller: 'DemoController', controllerAs: 'ctrl', template: '{{ctrl.tutorialName}}' }; }); </script> </body> </html>
代码说明
- 我们首先创建一个名为“DemoController”的控制器。在这里我们将定义一个名为“tutorialName”的变量,这次我们不会将它附加到范围对象,而是直接将它附加到控制器。
- 在我们的自定义指令中,我们特别提到我们要通过使用控制器参数关键字来使用控制器“DemoController”。
- 我们使用“controllerAs”参数创建对控制器的引用。这是由 Angular 定义的,是将控制器作为引用的方式。
- 最后,在我们的模板中,我们使用在步骤 3 中创建的引用,并使用在步骤 1 中直接附加到控制器的成员变量。
注意: -可以通过指定控制器、controllerAs 和模板语句的相应块来访问指令中的多个控制器。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
输出清楚地显示自定义指令特别访问 DemoController 和附加到它的成员变量 tutorialName,并显示文本“Angular”。
如何创建可重用指令
我们已经看到了自定义指令的强大功能,但我们可以通过构建我们自己的可重用指令将其提升到一个新的水平。
例如,假设我们想要注入代码,使之始终在多个屏幕上显示以下 HTML 标签,这基本上只是用户“姓名”和“年龄”的输入。
为了在多个屏幕上重复使用此功能而无需每次都进行编码,我们在 angular 中创建一个主控件或指令来保存这些控件(用户的“姓名”和“年龄”)。
所以现在,我们不必每次都为下面的屏幕输入相同的代码,而是可以将此代码嵌入到指令中并在任何时间点嵌入该指令。
让我们看一个例子来了解如何实现这一点。
<!DOCTYPE html> <html> <head> <meta chrset="UTF 8"> <title>Event Registration</title> </head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp"> <div ng-guru=""></div> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.directive('ngGuru',function(){ return { template: ' Name <input type="text"><br><br> Age<input type="text">' }; }); </script> </body> </html>
代码说明
- 在我们的自定义指令的代码片段中,改变的只是赋予自定义指令的模板参数的值。我们实际上输入的是需要显示在页面上的“姓名”和“年龄”的 2 个输入控件的整个片段,而不是计划五个标签或文本。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
从上面的输出中,我们可以看到自定义指令模板的代码片段已添加到页面中。
AngularJS 指令和组件 – ng-transclude
正如我们之前提到的,Angular 旨在扩展 HTML。我们已经了解了如何通过使用自定义可重用指令来实现代码注入。
但在现代 Web 应用程序开发中,还有开发 Web 组件的概念。这基本上意味着创建我们自己的 HTML 标签,这些标签可用作代码中的组件。
因此,Angular 通过提供将属性注入 HTML 标签本身的能力,为扩展 HTML 标签提供了另一层次的功能。
这是通过“ng-transclude”标签,这是一种设置,用于告诉 angular 捕获标记中指令内的所有内容。
让我们举一个例子来说明如何实现这一点。
<!DOCTYPE html> <html> <head> <meta chrset="UTF 8"> <title>Event Registration</title> </head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp"> <pane title="{{title}}">Angular JS</pane> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.directive('pane',function(){ return { transclude:true, scope :{title:'@'}, template: '<div style="border: 1px solid black;"> '+ '<ng-transclude></ng-transclude>'+ '</div>' }; }); </script> </body> </html>
代码说明
- 我们使用该指令定义一个名为“pane”的自定义 HTML 标签,并添加一个函数,该函数将为该标签添加一些自定义代码。在输出中,我们的自定义窗格标签将在带有纯黑色边框的矩形中显示文本“AngularJS”。
- 必须将“transclude”属性设置为 true,这是 angular 将此标签注入到我们的 DOM 中所必需的。
- 在范围内,我们定义了一个 title 属性。属性通常定义为名称/值对,如:name=”value”。在我们的例子中,窗格 HTML 标记中属性的名称是“title”。“@”符号是 angular 的要求。这样做是为了在步骤 5 中执行行 title={{title}} 时,title 属性的自定义代码会添加到窗格 HTML 标记中。
- 标题属性的自定义代码仅为我们的控件绘制一个实心黑色边框。
- 最后,我们调用自定义 HTML 标签以及定义的标题属性。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
- 输出清楚地显示窗格 html5 标签的 title 属性已设置为自定义值“Angular.JS”。
嵌套指令
AngularJS 中的指令可以嵌套。就像任何内部模块或函数一样 编程语言,您可能需要在彼此内嵌入指令。
通过查看下面的示例,您可以更好地理解这一点。
在这个例子中,我们创建了两个名为“outer”和“inner”的指令。
- inner 指令显示名为“Inner”的文本。
- 而外部指令实际上调用内部指令来显示名为“Inner”的文本。
</head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp"> <outer></outer> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.directive('outer',function(){ return { restrict:'E', template: '<div><h1>Outer</h1><inner></inner></div>', }}); app.directive('inner',function(){ return { restrict:'E', template: '<div><h1>Inner</h1></div>', } }); </script> </body> </html>
代码说明
- 我们正在创建一个名为“outer”的指令,它将充当我们的父指令。然后,该指令将调用“inner”指令。
- angular 要求 restrict:'E',以确保内部指令的数据可供外部指令使用。字母“E”是单词“Element”的缩写形式。
- 这里我们创建内部指令,在 div 标签中显示文本“Inner”。
- 在外部指令的模板中(步骤#4),我们调用内部指令。因此,在这里我们将模板从内部指令注入到外部指令。
- 最后,我们直接调用外部指令。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
从输出来看,
- 可以看出,outer 和 inner 指令都已被调用,并且两个 div 标签内的文本均被显示出来。
处理指令中的事件
活动 此类鼠标点击或按钮点击可在指令本身内处理。这可通过使用链接函数完成。链接函数允许指令将自身附加到 HTML 页面中的 DOM 元素。
语法:
link元素的语法如下所示
link: function ($scope, element, attrs)
链接函数通常接受3个参数,包括范围、指令所关联的元素以及目标元素的属性。
让我们看一个例子来了解如何实现这一点。
<!DOCTYPE html> <html> <head> <meta chrset="UTF 8"> <title>Event Registration</title> </head> <body> <script src="https://code.angularjs.org/1.6.9/angular-route.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <script src="https://code.angularjs.org/1.6.9/angular.min.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp"> <div ng-guru="">Click Me</div> </div> <script type="text/javascript"> var app = angular.module('DemoApp',[]); app.directive('ngGuru',function(){ return { link:function($scope,element,attrs) { element.bind('click',function () { element.html('You clicked me'); });} }}); </script> </body> </html>
代码说明
- 我们使用 angular 中定义的链接函数来赋予指令访问 HTML DOM 中事件的能力。
- 我们使用“element”关键字,因为我们想要响应 HTML DOM 元素的事件,在我们的例子中,该元素是“div”元素。然后我们使用“bind”函数,并表示我们想要向元素的点击事件添加自定义功能。“click”一词是关键字,用于表示任何 HTML 控件的点击事件。例如,HTML 按钮控件具有点击事件。由于在我们的示例中,我们想要向“dev”标签的点击事件添加自定义代码,因此我们使用“click”关键字。
- 这里我们说的是,我们想要用文本“你点击了我!”替换元素(在我们的例子中是 div 元素)的内部 HTML。
- 在这里我们定义 div 标签以使用 ng-guru 自定义指令。
如果代码成功执行,则在浏览器中运行代码时将显示以下输出。
输出:
- 最初,将向用户显示文本“Click Me”,因为这是 div 标签中最初定义的内容。当您实际单击 div 标签时,将显示以下输出
结语
- 还可以创建一个自定义指令,用于在主角度应用程序中注入代码。
- 可以使用“Controller”、“controllerAs”和“template”关键字使自定义指令调用某个控制器中范围对象中定义的成员。
- 指令还可以嵌套以提供根据应用程序的需要而可能需要的嵌入式功能。
- 指令也可以重复使用,以便它们可以用于注入各种 Web 应用程序可能需要的通用代码。
- 指令还可用于创建自定义 HTML 标签,这些标签将根据业务需求定义自己的功能。
- 还可以从指令内部处理事件来处理 DOM 事件,例如按钮和鼠标点击。