Example 应用程序lication wireframe with separate 组件 sections colored out< / div >
根据上面的截图, 我们可以清楚地看到应用程序的结构是这样的:
──myTasksApplication
├──组件
│├──header-menu.组件.ts
│├──header-menu.组件.html
│├──rammstein.组件.ts
│││任务列表.组件.html
├──页面
│├──即将完成的任务.组件.ts
│├──即将完成的任务.组件.html
│├──已完成的任务.组件.ts
│││完成的任务.组件.html
├──应用.组件.ts
└──应用.组件.html
So let’s link the 组件 files with the actual elements on the wireframe above:
-
header-menu.组件
和 任务列表.组件
是可重用的组件,在线框截图中以绿色边框显示;
-
接下来要完成的任务.组件
和 完成的任务.组件
are 页面, which are displayed with a yellow border in the wireframe screenshot above; 和
- 最后,
应用程序.组件
是根组件,在线框截图中显示为红色边框.
因此,话虽如此,我们可以为每个组件指定单独的逻辑和设计. Based on the wireframes above, we have two 页面 that reuse one 组件—任务列表.组件
. 问题来了——我们如何指定在特定页面上显示什么类型的数据? 幸运的是, 我们不用担心这个, 因为当你创建一个组件时, 你也可以指定 Input 和 Output 变量.
在组件中使用输入变量来传递来自父组件的一些数据. 在上面的例子中, we could have two input parameters for the 任务列表.组件
—任务
和 listType
. 因此, 任务
将是一个字符串列表,它将在单独的行上显示每个字符串,而 listType
要么 即将到来的 or 完成,这将指示复选框是否被选中. Below, you can find a small code snippet of how the actual 组件 could look.
/ /任务列表.组件.ts
从“@angular/core”中导入{Component, Input};
@ 组件 ({
选择器:“应用程序-任务列表”,
templateUrl:“任务列表.组件.html的
})
导出类TaskListComponent {
@Input() 任务: string[] = []; // List of 任务 which 应该 be displayed.
@Input() listType: “即将” | '完成' = “即将”; // Type of the task list.
构造函数(){}
}
输出变量
类似于输入变量, output 变量 can be also used to pass some information between the 组件s, 但这次是父组件. 例如,对于 任务列表.组件
,我们可以有输出变量 itemChecked
. It would inform the parent 组件 if an item has been checked or unchecked. 输出变量必须为 事件发射器. 下面,您可以找到一小段代码片段,其中显示了使用输出变量时组件的外观.
/ /任务列表.组件.ts
从“@angular/core”中导入{Component, Input, Output};
@ 组件 ({
选择器:“应用程序-任务列表”,
templateUrl:“任务列表.组件.html的
})
导出类TaskListComponent {
@Input() 任务: string[] = []; // List of 任务 which 应该 be displayed.
@Input() listType: “即将” | '完成' = “即将”; // Type of the task list.
@Output() itemChecked: EventEmitter = new EventEmitter();
@Output() 任务Change: EventEmitter = new EventEmitter();
构造函数(){}
/**
当列表中的项被选中时调用.
* @param selected---Value which indicates if the item is selected or deselected.
*/
onItemCheck(选中:boolean) {
这.itemChecked.发出(选择);
}
/**
当任务列表被更改时调用.
* @param changedTasks——修改任务列表的值,该值应该发送给父组件.
*/
onTasksChanged(changedTasks: string[]) {
这.taskChange.发出(changedTasks);
}
}
可能的
任务列表.组件.ts
添加输出变量后的内容< / div >
子组件使用和变量绑定
让我们看一下如何在父组件中使用这个组件,以及如何进行不同类型的变量绑定. 在角, there are two ways to bind the input 变量—one-way binding, which means that the property must be wr应用程序ed in square brackets []
以及双向绑定,这意味着必须将属性包装在方括号和圆括号中 [()]
. 看看下面的例子,看看数据在组件之间传递的不同方式.
Upcoming Tasks
<应用程序-任务列表 [(任务)]="即将到来的Tasks" [listType]="“即将”" (itemChecked)="onItemChecked(美元的事件)">应用程序-任务列表>
可能的
接下来要完成的任务.组件.html
内容< / div >
让我们来看看每个参数:
- 的
任务
参数使用双向绑定传递. 这意味着, in case the 任务 parameter is changed within the child 组件, 父组件将把这些更改反映到 即将到来的Tasks
变量. 允许双向数据绑定, 您必须创建一个输出参数, 它跟在模板" [inputParameterName]Change "后面, 在这种情况下 任务Change
.
- 的
listType
参数使用单向绑定传递. 这意味着 it can be changed within the child 组件, 但它不会反映在父组件中. 记住,我可以赋值 “即将”
到组件内的一个参数,并传递它,这没有什么区别.
- 最后,
itemChecked
parameter is a listener function, 和 it will be called whenever onItemCheck 在 任务列表.组件
. 如果选中了某项, 美元的事件
会保持这个值 真正的
,但是,如果未选中,它将保存该值 假
.
如你所见, 在一般情况下, 角提供了一种在多个组件之间传递和共享信息的好方法, 所以你不应该害怕使用它们. 只是要确保明智地使用它们,不要过度使用它们.
何时创建一个单独的角组件
如前所述, 你不应该害怕使用角组件, 但你绝对应该明智地使用它们.
< / div >
明智地使用角组件< / div >
所以,当 你应该 创建角组件?
- 你 应该总是 如果组件可以在多个地方被重用,就创建一个单独的组件
任务列表.组件
. 我们称之为 可重用组件.
- 你 应该考虑 创建一个单独的组件,如果该组件将使父组件更具可读性,并允许它们添加额外的测试覆盖. 我们可以打电话给他们 代码组织组件.
- 你 应该总是 如果页面的一部分不需要经常更新,并且希望提高性能,则创建一个单独的组件. 这与变更检测策略有关. 我们可以打电话给他们 优化组件.
的se three rules help me identify if I need to create a new 组件, 和 they automatically give me a clear vision of the role for the 组件. 在理想的情况下, 创建组件时, you 应该 already know what its role will be within the 应用程序lication.
因为我们已经学习了的用法 可重用组件,我们来看看的用法 代码组织组件. 假设我们有一个注册表单,在表单的底部,我们有一个带有 条款与条件. 通常, 法律术语往往非常庞大, 在这种情况下,占用了很多空间, 在HTML模板中. So, let’s look at 这 example 和 then see how we could potentially change it.
一开始,我们有一个分量-登记.组件
-容纳一切, including the 登记 form as well as the terms 和 conditions themselves.
Registration
文本非常长的条款和条件.
Initial state before separating 登记.组件 into multiple 组件s< / div >
的 template now looks small, but imagine if we would replace “带有很长条款和条件的文本” 对于超过1000个单词的实际文本,这将使文件的编辑变得困难和不舒服. We have a quick solution for that—we could invent a new 组件 条款和条件.组件
, which would hold everything related to terms 和 conditions. 让我们看一下HTML文件 条款和条件.组件
.
文本非常长的条款和条件.
Newly created 条款和条件.组件 HTML template< / div >
现在我们可以调整 登记.组件
然后使用 条款和条件.组件
在它的内部.
Registration
<应用程序-条款和条件>应用程序-条款和条件>
Updated 登记.组件.ts template with code organization 组件< / div >
祝贺你! 我们刚刚减小了 登记.组件
减少了数百行,使代码更容易阅读. 在上面的例子中, 我们对组件的模板进行了更改, but the same principle could be 应用程序lied to the logic of the 组件.
最后,对于 优化组件,我强烈建议你通过 这篇文章, 因为它将为您提供理解变更检测所需的所有信息, 以及你可以将其应用于哪些具体情况. 你不会经常使用它, 但可能会有一些情况, 和 if you can skip regular checks on multiple 组件s when it’s not necessary, 这是一个双赢的表现.
话虽如此, 我们不应该总是创建单独的组件, so let’s have a look when you 应该 avoid creating a separate 组件.
何时避免创建单独的角组件
基于这三点,我建议创建一个单独的角组件, but there are cases in which I would avoid creating a separate 组件 as well.
< / div >
太多的组件会减慢你的速度.< / div >
再一次,让我们来看看要点,这些要点可以让你很容易地理解 不应该 创建一个单独的组件.
- 你 不应该 为DOM操作创建组件. 对于这些,您应该使用 属性指示.
- 你 不应该 创建组件,如果它将使您的代码更混乱. 这是相反的 代码组织组件.
现在, let’s take a closer look 和 check out both cases in examples. Let’s imagine that we want to have a button that logs the message when it’s clicked. 这可能是错误的,并且可能为此特定功能创建单独的组件, 哪一个可以容纳特定的按钮和操作. 让我们先检查一下不正确的方法:
/ / log键.组件.ts
从“@angular/core”中导入{Component, Input, Output};
@ 组件 ({
选择器:“应用程序-log键”,
templateUrl:“log键.组件.html的
})
导出类LogButtonComponent {
@Input() name: string; // Name of the button.
@Output() buttonClicked: EventEmitter = new EventEmitter();
构造函数(){}
/**
当按钮被点击时调用.
* @param clicked - Value which indicates if the button was clicked.
*/
onButtonClick(click: boolean) {
控制台.log(“我刚刚点击了这个网站上的一个按钮”);
这.buttonClicked.发出(点击);
}
}
不正确组件的逻辑
log键.组件.ts
< / div >
And accordingly, 这 组件 is accompanied with the following html view.
错误组件模板
log键.组件.html
< / div >
如你所见, 上面的例子可以工作, 您可以在整个视图中使用上述组件. 从技术上讲,它会做你想做的事. 但正确的解决方案是使用指令. 这样不仅可以减少必须编写的代码量,还可以将此功能应用于所需的任何元素, 不仅仅是按钮.
从“@angular/core”中导入{Directive};
@Directive ({
选择器:“[logButton]”,
hostListeners: {
“点击”:“onButtonClick()”,
},
})
类LogButton {
构造函数(){}
/**
*当元素被点击时触发.
*/
onButtonClick () {
控制台.log(“我刚刚点击了这个网站上的一个按钮”);
}
}
logButton
指令,它可以被赋值给任何元素< / div >
现在我们创建了指令, we can simply use it across our 应用程序lication 和 assign it to any element we want. 例如,让我们重用我们的 登记.组件
.
Registration
<应用程序-条款和条件>应用程序-条款和条件>
logButton
在注册表格按钮上使用的指令< / div >
现在, 我们来看看第二种情况, 其中我们不应该创建单独的组件, 这和 代码优化组件. If the newly-created 组件 makes your code more complicated 和 larger, 没有必要创建它. 让我们以……为例 登记.组件
. 其中一种情况是为标签和带有大量输入参数的输入字段创建一个单独的组件. 让我们来看看这个坏习惯.
/ / form-input-with-label.组件.ts
从“@angular/core”中导入{Component, Input};
@ 组件 ({
选择器:“应用程序-form-input-with-label”,
templateUrl:“form-input-with-label.组件.html的
})
导出类formminputwithlabel组件 {
@Input() name: string; // Name of the field
@Input() id: string; // Id of the field
@Input() label: string; // Label of the field
@Input() type: 'text' | 'password'; // Type of the field
@Input() model: any; // Model of the field
构造函数(){}
}
逻辑
form-input-with-label.组件
< / div >
这可以是这个组件的视图.
视野
form-input-with-label.组件
< / div >
当然,代码的数量会减少 登记.组件
,但它是否使代码的整体逻辑更容易理解和可读性? 我认为我们可以清楚地看到,它使代码比以前不必要地更加复杂.
下一步:角组件?
To summarize: Don’t be afraid to use 组件s; just make sure that you have a clear vision about what you want to achieve. 我上面列出的场景是最常见的, 和 I consider them to be the most important 和 common ones; however, your scenario may be unique 和 it’s up to you to make an informed decision. 我希望你已经学到了足够的东西,可以做出正确的决定.
如果你想了解更多关于角的变更检测策略和OnPush策略, 我推荐阅读 角变化检测和OnPush策略. 它与组件和密切相关, 正如我在帖子中提到的, it can significantly improve the performance of the 应用程序lication.
Since 组件s are only part of the directives that 角 provides, 要是能了解一下就太好了 属性指示 和 结构指示. 理解所有的指令很可能使程序员更容易写出更好的代码.
< / div >< / div >< / div >
< / div >
了解基本知识
角中有什么类型的指令啊?
的re are 组件 directives, 属性指示, 和 结构指示.
< / div >< / div >
什么是角选择器?
A selector is a way how a 组件 is called in a template. 它是组件的唯一标识符.
< / div >< / div >
什么是角组件?
组件是一个带有模板的指令,它允许在角应用中构建UI模块. 组件总是有一个模板、一个选择器,并且可能有也可能没有单独的样式. 使用@Component声明组件.
< / div >< / div >
什么是角模板?
角模板定义组件的UI.
< / div >< / div >
角中的属性指令是什么?
Attribute directives change the way how the DOM element 应用程序ears or behaves. Attributes do not have a template 和 are declared using @Directive.
< / div >< / div >
什么是角?
角 is a platform that allows users to easily build web 应用程序lications. 它是基于TypeScript的.
< / div >< / div >
什么是TypeScript?
TypeScript是一种脚本语言,它起源于JavaScript,并且是JavaScript的超集.
< / div >< / div >< / div >< / div >
标签
< / div >< / div >< / div >< / div >
就这一主题咨询作者或专家.< / div >
预约电话< / div >< / div >