angular绑定数据
数据绑定 (Data Binding)
动机 (Motivation)
Data often defines the look of an application. Interpreting that data into the user interface involves class logic (.component.html
) and a template view (.component.ts
) . Angular connects them through data binding. Think of data binding as a tool for component interaction.
数据通常定义应用程序的外观。 将数据解释为用户界面涉及类逻辑( .component.html
)和模板视图( .component.ts
)。 Angular通过数据绑定将它们连接起来。 可以将数据绑定视为组件交互的工具。
组件和模板 (Component and Template)
The component stores most of its logic and data inside of its class decorated with @Component
. This decorator defines the class as a component with template HTML. The template of the component represents the class within the application. The focus here needs to be between the component’s class and the template HTML.
该组件将其大多数逻辑和数据存储在用@Component
装饰的@Component
。 该装饰器将类定义为带有模板HTML的组件。 组件的模板表示应用程序中的类。 这里的焦点需要在组件的类和模板HTML之间。
This is where data binding occurs. Element properties and events get assigned values. These values, defined by the component class, serve either one of two roles. One is to produce data that the template then receives. The other handles events emitted by the template element.
这是发生数据绑定的地方。 元素属性和事件获得分配的值。 由组件类定义的这些值充当两个角色之一。 一种是产生模板随后接收的数据。 另一个处理模板元素发出的事件。
Try to use this picture as a mental model for the next section.
尝试将此图片用作下一部分的思维模型。
装订方向 (Directions of Binding)
There are two ways in which data is bound: unidirectional and bidirectional. Angular technically only uses unidirectional data flow. Bidirectional flow is ultimately unidirectional. It happens in two applications of unidirectional flow, once for each direction. More on that later.
数据绑定有两种方式:单向和双向。 角度技术上仅使用单向数据流。 双向流最终是单向的。 它在单向流的两种应用中发生,每个方向一次。 以后再说。
Unidirectional flow defines one-way interaction. Either the component sends data to the template or the template emits an event to the component logic. Data changes within scope of the template are not percolate to the component class. Event emitting is a one-way transaction beginning from the template’s elements.
单向流定义了单向交互。 组件将数据发送到模板,或者模板将事件发送到组件逻辑。 模板范围内的数据更改不会渗透到组件类中。 事件发射是从模板元素开始的单向事务。
Bidirectional constitutes both directions. This means changes to the data in the class logic or template HTML persist across each other. The scope of the changes are the component’s view. The view comprises the component’s class and template together.
双向构成两个方向。 这意味着对类逻辑或模板HTML中的数据的更改会彼此保留。 更改的范围是组件的视图。 该视图包括组件的类和模板。
元素属性 (Element Properties)
To recognize data-bound element properties, Angular uses a special bracket syntax.
为了识别数据绑定元素的属性,Angular使用特殊的括号语法。
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
value:type = /* some value of type */;
}
<!-- my.component.html -->
<any-element [property]=“value”>innerHTML</any-element>
Bear with me on this one.
忍受我这个。
[property]
mirrors the property in the Domain Object Model (DOM) element’s object node. Do not confuse object properties with a DOM element’s attributes. Properties and attributes often share the same name and do the same thing. There is one clear distinction however.
[property]
镜像域对象模型(DOM)元素的对象节点中的属性。 不要将对象属性与DOM元素的属性混淆。 属性和属性通常共享相同的名称并执行相同的操作。 但是,有一个明显的区别。
Remember that attr
(attributes) is a single property of the underlying DOM object. It gets declared at the DOM’s instantiation with attribute values matching the element’s definition. It maintains the same value after that. Properties each have their own key-value field in a DOM object node. These properties are mutable post-instantiation.
请记住, attr
(属性)是基础DOM对象的单个属性。 它在DOM的实例中被声明为具有与元素定义匹配的属性值。 之后,它将保持相同的值。 每个属性在DOM对象节点中都有自己的键值字段。 这些特性在实例化后是可变的。
Know the difference between attributes and properties. It will lead to a better understanding of how Angular binds data to properties (property binding). Angular will hardly ever bind data to an element’s attributes. Exceptions to this are very rare. One last time: Angular binds component data to properties, not attributes!
了解属性和属性之间的区别。 它将使您更好地了解Angular如何将数据绑定到属性(属性绑定)。 Angular几乎不会将数据绑定到元素的属性。 很少有例外。 最后一次:Angular将组件数据绑定到属性,而不是属性!
Referring back to the example, the [ … ]
in the element’s property assignment have special meaning. The brackets show that property
is bound to “value”
on the right of the assignment.
再次参考示例,元素属性分配中的[ … ]
具有特殊含义。 方括号显示property
绑定到分配右侧的“value”
。
value
also has special meaning within context of the brackets. value
by itself is a string literal. Angular reads it and matches its value against component class members. Angular will substitute the value of the matching member attribute. This of course refers to the same component class that hosts the template HTML.
value
在方括号内也有特殊含义。 value
本身就是字符串文字。 Angular读取它,并将其值与组件类成员匹配。 Angular将替换匹配成员属性的值。 当然,这是指托管模板HTML的相同组件类。
The unidirectional flow of data from component to template is complete. The member matched against right assignment of the bracketed property provides the value
. Note that changes to the member’s value in the component class percolate down to the template. That is Angular’s change detection at work. Changes within the template’s scope have no effect on the component class member.
从组件到模板的单向数据流已完成。 与右括号属性匹配的成员提供value
。 请注意,在组件类中对成员值的更改会渗透到模板中。 那就是Angular在工作中的变更检测。 模板范围内的更改对组件类成员没有影响。
Key take-away: the component class provides the data while the template displays it.
关键要点:组件类在模板显示时提供数据。
I failed to mention that data values can also show up in a component’s innerHTML
. This last example implements double curly braces. Angular recognizes these braces and interpolates the matching component class data into the innerHTML
of the div
.
我没有提到数据值也可以显示在组件的innerHTML
。 最后一个示例实现了双花括号。 Angular识别出这些花括号,并将匹配的组件类数据插入到div
的innerHTML
中。
<div>The value of the component class member ‘value’ is {{value}}.</div>
事件处理 (Event Handling)
If the component supplies data, then the template supplies events.
如果组件提供数据,则模板提供事件。
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
handler(event):void {
// function does stuff
}
}
// my.component.html
<any-element (event)=“handler($event)”>innerHTML</any-element>
This works similarly to property binding.
这类似于属性绑定。
The (event)
pertains to any valid event type. For example, one of the most common event types is click
. It emits when you click your mouse. Regardless of the type, event
is bound to “handler”
in the example. Event handlers are usually member functions of the component class.
(event)
与任何有效的事件类型有关。 例如, click
是最常见的事件类型之一。 当您单击鼠标时,它会发出。 在示例中,无论类型如何, event
都绑定到“handler”
。 事件处理程序通常是组件类的成员函数。
The ( … )
are special to Angular. Parenthesis tell Angular an event is bounded to the right assignment of handler
. The event itself originates from the host element.
( … )
对于Angular是特殊的。 括号告诉Angular事件绑定到handler
的正确分配。 事件本身起源于宿主元素。
When the event does emit, it passes the Event object in the form of $event
. The handler
maps to the identically named handler
function of the component class. The unidirectional exchange from the event-bound element to the component class is complete.
当事件确实发出时,它将以$event
的形式传递Event对象。 handler
映射到组件类的同名handler
函数。 从事件绑定元素到组件类的单向交换已完成。
Emitting events from the handler, while possible, do not impact the template element. The binding is unidirectional after all.
在可能的情况下,从处理程序中发出事件不会影响模板元素。 绑定毕竟是单向的。
双向绑定 (Bidirectional Binding)
Input forms provide a great example of why bidirectional binding is necessary. Bidirectional data bindings are more costly than event or property bindings.
输入表单提供了一个很好的示例,说明为什么必须进行双向绑定。 双向数据绑定比事件或属性绑定的成本更高。
Bidirectional data binding has its own module. Before taking a look at that, consider the following example.
双向数据绑定具有其自己的模块。 在查看之前,请考虑以下示例。
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
inputValue:string = "";
handler(event) {
this.inputValue = event.target.value;
}
}
<!-- my.component.html -->
<input (input)=“handler($event)” [value]=“inputValue”>
Time to break this down.
是时候分解这个了。
This example combines the previous two. That explains why it is more costly. Following the logic, assume the user types something into the input element. The element emits an input
event to the handler
of the template’s component class. The handler assigns the class member inputValue
to the value of the emitted event. This concludes the event handling/binding.
此示例结合了前两个。 这就解释了为什么它更昂贵。 按照逻辑,假设用户在输入元素中输入了一些内容。 元素向模板的组件类的handler
发出input
事件。 处理程序将类成员inputValue
分配给发出的事件的值。 到此,事件处理/绑定结束。
Now onto the property binding. The inputValue
was assigned a new value. Since inputValue
is bound to the input element’s value
, its change in data percolates down into the input element’s value
property. The input element’s value
matches up with inputValue
. This concludes the property binding.
现在到属性绑定。 为inputValue
分配了一个新值。 由于inputValue
绑定到输入元素的value
,因此其数据更改会渗入到input元素的value
属性中。 输入元素的value
与inputValue
匹配。 这样就结束了属性绑定。
There you have it. Bidirectional data binding happens with both applications of unidirectional binding applied consecutively. The syntax is a bit messy though.
你有它。 双向数据绑定是在连续应用单向绑定的两个应用程序时发生的。 语法有点混乱。
Thankfully, Angular provides NgModel
to simplify the syntax. The below example is synonymous to the above.
幸运的是,Angular提供了NgModel
来简化语法。 以下示例与以上同义。
// my.component.ts
@Component({
templateUrl: ‘./my.component.html’
})
export class MyComponent {
inputValue:string = "";
}
<!-- my.component.html -->
<input [(ngModel)]=“inputValue”>
ngModel
is a nice convenience. You have to import the FormsModule in your application’s root before using it. With that squared away, bidirectional data binding becomes much easier to work with.
ngModel
非常方便。 使用前,您必须在应用程序的根目录中导入FormsModule。 有了这个平方,双向数据绑定就变得更容易使用。
To reinforce all you have learned, check out this picture from the official Angular Documentation1.
为了增强您所学的知识,请从官方Angular文档1中查看此图片。
You can visually summarize everything up until this point with this picture. Angular’s Documentation has plenty of other pictures worth seeing. This one should suffice given the scope of this article.
您可以使用这张图片直观地总结到目前为止的所有内容。 Angular的文档中还有许多其他图片值得一看。 考虑到本文的范围,这一点就足够了。
组件到组件 (Component to Component)
To bind data and events across different components, you must use the @Input and @Output decorators. Angular components are privately scoped. None of a component’s members are accessible from anywhere outside of its native view.
若要跨不同组件绑定数据和事件,必须使用@Input和@Output装饰器。 角组件是私有范围的。 组件的成员均无法从其本机视图之外的任何位置访问。
The @Input decorator indicates a member’s value is sourced from the parent function. This requires visualization to better understand.
@Input装饰器指示成员的值来自父函数。 这需要可视化以更好地理解。
Notice the passing of the parent’s value
member into the child’s property
member. This would not be possible if property
had no @Input decorator. The Angular compiler depends upon it.
注意将父级的value
成员传递给子级的property
成员。 如果property
没有@Input装饰器,则将无法执行此操作。 Angular编译器依赖于此。
Another example for @Output shows how an event travels from child to parent. Keep in mind that @Output almost always pertains to custom event bindings.
@Output的另一个示例显示事件如何从子级传播到父级。 请记住,@ Output几乎总是与自定义事件绑定有关。
Make sure you import EventEmitter
, @Input
, and @Output
from @angular/common
if you intend to replicate either of these examples.
如果打算复制这些示例中的任何一个,请确保从@angular/common
导入EventEmitter
, @angular/common
@Input
和@Output
。
结论 (Conclusion)
This is a good place to stop. Data binding spans a wide array of use cases. This topic is worth exploring further on Angular’s website. These are not the only ways that you can manipulate data in Angular. See the links under Resources for more information.
这是一个好地方。 数据绑定涵盖了广泛的用例。 值得在Angular网站上进一步探讨该主题。 这些不是您可以在Angular中操作数据的唯一方式。 有关更多信息,请参见参考资料下的链接。
翻译自: https://www.freecodecamp.org/news/data-binding-in-angular-explained/
angular绑定数据