首页 >> 大全

掌握AngularJS指令

2023-09-05 大全 34 作者:考证青年

app.directive("item", function() {return {restrict: 'E',link: function(scope, element, attrs) {scope.name = attrs.name;},template: '
Name: {{name}} Select Amount: Selected Amount: {{count}}
'} })

并且为了显示HTML中的三个项目:



这里的问题是,每当您选择所需项目的金额时,项目的所有金额部分都会被更新。 为什么? 因为存在带有名称count的双向数据绑定,但是作用域不是孤立的。 为了隔离范围,只需添加scope: {} 返回部分的指令属性:

app.directive("item", function() {return {restrict: 'E',scope: {},link: function(scope, element, attrs) {scope.name = attrs.name;},template: '
Name: {{name}} Select Amount: Selected Amount: {{count}}
'} })

这导致您的指令具有自己的隔离范围,因此双向数据绑定将在此指令内单独进行。 我还会提到scope 稍后属性。

4.指令范围

该指令的主要优点是它是一个易于使用的可重用组件,您甚至可以为该指令提供一些其他属性 。 但是,如何将附加值,绑定或表达式传递给指令,以便在指令内部使用数据?

“ @”作用域:这种类型的作用域用于将值传递给指令作用域。 假设您要为通知消息创建小部件:

app.controller("MessageCtrl", function() {$scope.message = "Product created!";
})
app.directive("notification", function() {return {restrict: 'E',scope: {message: '@'},template: '
{{message}}
'} });

您可以使用:

在此示例中,仅将消息值分配给指令范围。 呈现HTML内容将为:

Product created!

“ =”范围:在此范围类型中,将传递范围变量而不是值,这意味着我们将不传递{{}} ,而是传递 。 此功能背后的原因是在指令与页面元素或控制器之间构造双向数据绑定。 让我们来看看它的作用。

.directive("bookComment", function() {return {restrict: 'E',scope: {text: '='},template: ''}
})

在此指令中,我们试图创建一个小部件来显示注释文本输入,以对特定书籍进行注释。 如您所见,此伪指令需要一个属性text来构造页面上其他元素之间的双向数据绑定。 您可以在页面上使用它:

This is the textbox on the directive

这只会在页面上显示一个文本框,因此让我们添加更多内容与该指令交互:

This is the textbox on the page


This is the textbox on the directive

每当您在第一个文本框中键入内容时,也会在第二个文本框中键入内容。 反之亦然。 在指令中,我们传递了范围变量而不是值,并且此变量是对第一个文本框的数据绑定引用。

“&”范围:我们能够传递值,并引用指令。 在这种作用域类型中,我们将研究如何将表达式传递给指令。 在实际情况下,您可能需要将特定的函数(表达式)传递给指令,以防止耦合。 有时,指令不需要对表达式背后的概念有太多了解。 例如,一条指令会为您喜欢这本书,但它不知道该怎么做。 为此,您可以遵循以下结构:

.directive("likeBook", function() {return {restrict: 'E',scope: {like: '&'},template: ''}
})

在此指令中,表达式将通过like属性传递给指令按钮。 让我们在控制器中定义一个函数,并将其传递给HTML内部的指令。

$scope.likeFunction = function() {alert("I like the book!")
}

这将在控制器内部,并且模板将是:

()来自控制器,并传递给指令。 如果要将参数传递给()怎么办? 例如,您可能需要将等级值传递给() 。 这非常简单:只需在控制器内部的函数中添加参数,然后在指令中添加输入元素,以要求用户进行起始计数。 您可以如下所示进行操作:

.directive("likeBook", function() {return {restrict: 'E',scope: {like: '&'},template: '
' +''} })

$scope.likeFunction = function(star) {alert("I like the book!, and gave " + star + " star.")
}

如您所见,文本框来自指令。 文本框的值绑定到函数参数,例如like({star: }) 。 star用于控制器功能, 用于文本框值绑定。

5.指令继承

有时,您可能具有多个指令中存在的功能。 可以将它们放在父指令中,以便由子指令继承。

让我给你一个真实的例子。 您希望每当客户将鼠标光标移到特定书籍的顶部时发送统计数据。 您可以为book指令实现鼠标单击事件,但是如果另一个指令将使用该事件呢? 在这种情况下,可以使用如下指令的继承:

app.directive('mouseClicked', function() {return {restrict: 'E',scope: {},controller: "MouseClickedCtrl as mouseClicked"}
})

这是要由子指令继承的父指令。 如您所见,使用“ as”指令存在指令的控制器属性。 让我们也定义这个控制器:

app.controller('MouseClickedCtrl', function($element) {var mouseClicked = this;mouseClicked.bookType = null;mouseClicked.setBookType = function(type) {mouseClicked.bookType = type};$element.bind("click", function() {alert("Typeof book: " + mouseClicked.bookType + " sent for statistical analysis!");})
})

在此控制器中,我们仅使用子指令设置变量的控制器实例。 每当您单击一本书或杂志时,元素的类型都会发送到后端服务(我使用了警报功能只是为了显示数据)。 子指令将如何使用该指令?

app.directive('ebook', function() {return {require: "mouseClicked",link: function(scope, element, attrs, mouseClickedCtrl) {mouseClickedCtrl.setBookType("EBOOK");}}
})
.directive('magazine', function() {return {require: "mouseClicked",link: function(scope, element, attrs, mouseClickedCtrl) {mouseClickedCtrl.setBookType("MAGAZINE");}}
})

如您所见,子指令使用关键字来使用父指令。 还有一点很重要,就是子指令中链接函数的第四个参数。 此参数引用父指令的属性,这意味着子指令可以在控制器内部使用控制器函数 。 如果当前元素是电子书,则可以使用第一个指令,如果它是杂志,则可以使用第二个指令:

Game of thrones (click me)
PC World (click me)

子指令类似于父指令的属性。 我们通过将每个节放在父指令中来消除了每个子指令对mouse-click事件的使用。

6.指令调试

当您在模板中使用指令时,在页面上看到的是指令的编译版本。 有时,您希望查看实际的指令用法以进行调试。 为了查看当前部分的未编译版本,可以使用ng-non- 。 例如,假设您有一个可打印最受欢迎书籍的小部件,以下是该代码:

  • {{book}}

本书的范围变量来自控制器,其输出如下:

angularjs指令的作用__angular8自定义指令

如果您想了解此编译输出背后的指令用法,则可以使用以下版本的代码:

  • {{book}}

angular8自定义指令_angularjs指令的作用_

这次的输出将如下所示:

到现在为止还很酷,但是如果我们想同时看到小部件的未编译版本和已编译版本,该怎么办? 现在该编写一个可以执行高级调试操作的自定义指令了。

app.directive('customDebug', function($compile) {return {terminal: true,link: function(scope, element) {var currentElement = element.clone();currentElement.removeAttr("custom-debug");var newElement = $compile(currentElement)(scope);element.attr("style", "border: 1px solid red");element.after(newElement);}}
})

在此伪指令中,我们将克隆处于调试模式的元素,以便在进行某些操作后不会更改它。 克隆后,删除-debug 为了不充当调试模式,然后使用已经注入到指令中的$进行编译。 我们为调试模式元素提供了一种样式,以强调已调试的元素。 最终结果如下:

样本指令

通过使用这种调试指令来检测项目中任何错误的根本原因,可以节省开发时间。

7.指令单元测试

如您所知,单元测试是开发中非常重要的一部分,它可以完全控制您编写的代码并防止潜在的错误。 我不会深入探讨单元测试,但是会为您提供有关如何以几种方式测试指令的线索。

我将使用进行单元测试,使用Karma进行单元测试。 为了使用Karma,只需通过运行npm -g karma karma-cli全局npm -g karma karma-cli (您需要在计算机上安装Node.js和npm)。 安装后,打开命令行,转到项目根文件夹,然后键入karma init 。 它会询问您以下几个问题,以设置您的测试要求。

业力测试初始化

我正在使用进行开发,如果您还使用,则只需右键单击karma.conf.js并选择Run karma.conf.js。 这将执行karma conf中配置的所有测试。 您也可以使用项目根文件夹中的karma start命令行运行测试。 这就是环境设置的全部内容,因此让我们切换到测试部分。

假设我们要测试book指令。 将标题传递给指令时,应将其编译为书籍详细信息视图。 因此,让我们开始吧。

describe("Book Tests", function() {var element;var scope;beforeEach(module("masteringAngularJsDirectives"))beforeEach(inject(function($compile, $rootScope) {scope = $rootScope;element = angular.element("");$compile(element)($rootScope)scope.$digest()}));it("directive should be successfully compiled", function() {expect(element.html()).toBe("test")})
});

在上述测试中,我们正在测试一个名为的新指令。 该指令采用参数title 并使用此标题创建一个div。 在测试中,在每个测试部分之前,我们都将模块称为 第一。 然后,我们正在生成一个名为的指令。 在每个测试步骤中,将测试指令输出。 该测试仅用于值检查。

8.指令范围测试

在本节中,我们将测试指令的范围。 此伪指令在页面上生成一个书籍详细信息视图,当您单击此详细信息部分时,一个范围变量称为已 将设置为true 。 在我们的测试中,我们将检查是否 触发click事件时将其设置为true。 该指令是:

.directive('booktest', function() {return {restrict: 'E',scope: {title: '@'},replace: true,template: '
{{title}}
',link: function(scope, element, attrs) {element.bind("click", function() {console.log("book viewed!");scope.viewed = true;});}} })

为了在指令内的中将事件设置为元素,可以使用link属性。 在此属性内,您具有直接绑定到click事件的当前元素。 为了测试此指令,可以使用以下命令:

describe("Book Tests", function() {var element;var scope;beforeEach(module("masteringAngularJsDirectives"))beforeEach(inject(function($compile, $rootScope) {scope = $rootScope;element = angular.element("");$compile(element)($rootScope)scope.$digest()}));it("scope liked should be true when book liked", function() {element.triggerHandler("click");expect(element.isolateScope().viewed).toBe(true);});
});

在测试部分,使用.("click")触发click事件。 触发点击事件时,需要将查看的变量设置为true 。 通过使用(.().).toBe(true)来声明该值。

9.结论

为了开发模块化和可测试的Web项目,是最好的工具。 指令是的最佳组件之一,这意味着您对指令了解得越多,您可以开发的模块和可测试项目就越多。

在本教程中,我试图向您展示有关指令的现实最佳实践,并牢记您需要做大量练习才能理解指令背后的逻辑。 我希望本文能帮助您更好地了解指令。

翻译自:

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了