加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Angular4_td中的colspan

发布时间:2020-12-17 08:25:11 所属栏目:安全 来源:网络整理
导读:td [attr.colspan]="progressCode == 'WAITING' ? 11: 10 " attribute、class 和 style 绑定 模板语法为那些不太适合使用属性绑定的场景提供了专门的单向数据绑定形式。 attribute 绑定 可以通过attribute 绑定来直接设置 attribute 的值。 这是“绑定到目标

<td [attr.colspan]="progressCode == 'WAITING' ? 11: 10 ">


attribute、class 和 style 绑定

模板语法为那些不太适合使用属性绑定的场景提供了专门的单向数据绑定形式。

attribute 绑定

可以通过attribute 绑定来直接设置 attribute 的值。

这是“绑定到目标属性 (property)”这条规则中唯一的例外。这是唯一的能创建和设置 attribute 的绑定形式。

本章中,通篇都在说通过属性绑定来设置元素的属性总是好于用字符串设置 attribute。为什么 Angular 还提供了 attribute 绑定呢?

因为当元素没有属性可绑的时候,就必须使用 attribute 绑定。

考虑ARIA,SVG和 table 中的 colspan/rowspan 等 attribute。 它们是纯粹的 attribute,没有对应的属性可供绑定。

如果想写出类似下面这样的东西,现状会令我们痛苦:

content_copy<tr><td colspan="{{1 + 1}}">Three-Four</td></tr></td></tr>

会得到这个错误:

content_copyTemplate parse errors: Can't bind to 'colspan' since it isn't a known native property (模板解析错误:不能绑定到 'colspan',因为它不是已知的原生属性)

正如提示中所说,<td>元素没有colspan属性。 但是插值表达式和属性绑定只能设置属性,不能设置 attribute。

我们需要 attribute 绑定来创建和绑定到这样的 attribute。

attribute 绑定的语法与属性绑定类似。 但方括号中的部分不是元素的属性名,而是由attr前缀,一个点 (.) 和 attribute 的名字组成。 可以通过值为字符串的表达式来设置 attribute 的值。

这里把[attr.colspan]绑定到一个计算值:

src/app/app.component.html
content_copy<table border1> <!-- expression calculates colspan=2 --> <tr><td [attr.colspan]"1 + 1">One-Two</td></tr> <!-- ERROR: There is no `colspan` property to set! <tr><td colspan="{{1 + 1}}">Three-Four</td></tr> --> <tr><td>Five</td><td>Six</td></tr> </table>

这里是表格渲染出来的样子:

One-Two
Five Six

attribute 绑定的主要用例之一是设置 ARIA attribute(译注:ARIA指可访问性,用于给残障人士访问互联网提供便利), 就像这个例子中一样:

src/app/app.component.html
content_copy<!-- create and set an aria attribute for assistive technology --> <button [aria-label]"actionName">{{actionName}} with Aria</button>

CSS 类绑定

借助CSS 类绑定,可以从元素的classattribute 上添加和移除 CSS 类名。

CSS 类绑定绑定的语法与属性绑定类似。 但方括号中的部分不是元素的属性名,而是由class前缀,一个点 (.)和 CSS 类的名字组成, 其中后两部分是可选的。形如:[class.class-name]

下列例子示范了如何通过 CSS 类绑定来添加和移除应用的 "special" 类。不用绑定直接设置 attribute 时是这样的:

src/app/app.component.html
content_copy<!-- standard class attribute setting --> <div class"bad curly special">Bad curly special</div>

可以把它改写为绑定到所需 CSS 类名的绑定;这是一个或者全有或者全无的替换型绑定。 (译注:即当 badCurly 有值时 class 这个 attribute 设置的内容会被完全覆盖)

src/app/app.component.html
content_copy<!-- reset/override all class names with a binding --> "bad curly special" [class]"badCurly">Bad curly最后,可以绑定到特定的类名。 当模板表达式的求值结果是真值时,Angular 会添加这个类,反之则移除它。

src/app/app.component.html
content_copy<!-- toggle the "special" class on/off with a property --> <div [class.special]"isSpecial">The class binding is special</div> <!-- binding to `class.special` trumps the class attribute --> "special" ["!isSpecial">This one is not so special</div>

虽然这是切换单一类名的好办法,但我们通常更喜欢使用NgClass指令来同时管理多个类名。


样式绑定

通过样式绑定,可以设置内联样式。

样式绑定的语法与属性绑定类似。 但方括号中的部分不是元素的属性名,而由style前缀,一个点 (.)和 CSS 样式的属性名组成。 形如:[style.style-property]

src/app/app.component.html
content_copystyle.color]"isSpecial ? 'red': 'green'">Red</button> background-color]"canSave ? 'cyan': 'grey'" >Save</button>

有些样式绑定中的样式带有单位。在这里,以根据条件用 “em” 和 “%” 来设置字体大小的单位。

src/app/app.component.html
content_copyfont-size.em]"isSpecial ? 3 : 1" >Bigfont-size.%]"!isSpecial ? 150 : 50" >Small</button>

虽然这是设置单一样式的好办法,但我们通常更喜欢使用NgStyle指令来同时设置多个内联样式。

注意,样式属性命名方法可以用中线命名法,像上面的一样 也可以用驼峰式命名法,如fontSize


事件绑定 ((事件名))

前面遇到的绑定的数据流都是单向的:从组件到元素。

但用户不会只盯着屏幕看。他们会在输入框中输入文本。他们会从列表中选取条目。 他们会点击按钮。这类用户动作可能导致反向的数据流:从元素到组件

知道用户动作的唯一方式是监听某些事件,如按键、鼠标移动、点击和触摸屏幕。 可以通过 Angular 事件绑定来声明对哪些用户动作感兴趣。

事件绑定语法由等号左侧带圆括号的目标事件和右侧引号中的模板语句组成。 下面事件绑定监听按钮的点击事件。每当点击发生时,都会调用组件的onSave()方法。

src/app/app.component.html
content_copy<button (click)"onSave()"</button>

目标事件

圆括号中的名称—— 比如(click)—— 标记出目标事件。在下面例子中,目标是按钮的 click 事件。

src/app/app.component.html
content_copy有些人更喜欢带on-前缀的备选形式,称之为规范形式:

src/app/app.component.html
content_copy<button on-click>On Save元素事件可能是更常见的目标,但 Angular 会先看这个名字是否能匹配上已知指令的事件属性,就像下面这个例子:

src/app/app.component.html
content_copy<!-- `myClick` is an event on the custom `ClickDirective` --> <div (myClick)"clickMessage=$event" clickable>click with myClick 
  

更多关于该myClick指令的解释,见给输入/输出属性起别名。

如果这个名字没能匹配到元素事件或已知指令的输出属性,Angular 就会报“未知指令”错误。

$event和事件处理语句

在事件绑定中,Angular 会为目标事件设置事件处理器。

当事件发生时,这个处理器会执行模板语句。 典型的模板语句通常涉及到响应事件执行动作的接收器,例如从 HTML 控件中取得值,并存入模型。

绑定会通过名叫$event的事件对象传递关于此事件的信息(包括数据值)。

事件对象的形态取决于目标事件。如果目标事件是原生 DOM 元素事件,$event就是DOM事件对象,它有像targettarget.value这样的属性。

考虑这个范例:

src/app/app.component.html
content_copy<input [value]"currentHero.name" (input)"currentHero.name=$event.target.value" >

上面的代码在把输入框的value属性绑定到firstName属性。 要监听对值的修改,代码绑定到输入框的input事件。 当用户造成更改时,input事件被触发,并在包含了 DOM 事件对象 ($event) 的上下文中执行这条语句。

要更新firstName属性,就要通过路径$event.target.value来获取更改后的值。

如果事件属于指令(回想一下,组件是指令的一种),那么$event具体是什么由指令决定。

使用EventEmitter实现自定义事件

通常,指令使用 AngularEventEmitter来触发自定义事件。 指令创建一个EventEmitter实例,并且把它作为属性暴露出来。 指令调用EventEmitter.emit(payload)来触发事件,可以传入任何东西作为消息载荷。 父指令通过绑定到这个属性来监听事件,并通过$event对象来访问载荷。

假设HeroDetailComponent用于显示英雄的信息,并响应用户的动作。 虽然HeroDetailComponent包含删除按钮,但它自己并不知道该如何删除这个英雄。 最好的做法是触发事件来报告“删除用户”的请求。

下面的代码节选自HeroDetailComponent

src/app/hero-detail.component.ts (template)
content_copytemplate: ` <div> <img src="{{heroImageUrl}}"> <span [style.text-decoration]="lineThrough"> {{prefix}} {{hero?.name}} </span> <button (click)="delete()">Delete</button> </div>`
src/app/hero-detail.component.ts (deleteRequest)
content_copy// This component makes a request but it can't actually delete a hero. deleteRequest = new EventEmitter<Hero>(); delete() { this.deleteRequest.emit(.hero); }

组件定义了deleteRequest属性,它是EventEmitter实例。 当用户点击删除时,组件会调用delete()方法,让EventEmitter发出一个Hero对象。

现在,假设有个宿主的父组件,它绑定了HeroDetailComponentdeleteRequest事件。

src/app/app.component.html (event-binding-to-component)
content_copy<app-hero-detail (deleteRequest)"deleteHero($event)" [hero]"currentHero"></app-hero-detail>

deleteRequest事件触发时,Angular 调用父组件的deleteHero方法, 在$event变量中传入要删除的英雄(来自HeroDetail)。

模板语句有副作用

deleteHero方法有副作用:它删除了一个英雄。 模板语句的副作用不仅没问题,反而正是所期望的。

ThedeleteHeromethod has a side effect: it deletes a hero. Template statement side effects are not just OK,but expected.

删除这个英雄会更新模型,还可能触发其它修改,包括向远端服务器的查询和保存。 这些变更通过系统进行扩散,并最终显示到当前以及其它视图中。


双向数据绑定 ([(...)])

我们经常需要显示数据属性,并在用户作出更改时更新该属性。

在元素层面上,既要设置元素属性,又要监听元素事件变化。

Angular 为此提供一种特殊的双向数据绑定语法:[(x)][(x)]语法结合了属性绑定的方括号[x]事件绑定的圆括号(x)

[( )] = 盒子里的香蕉

想象盒子里的香蕉来记住方括号套圆括号。

当一个元素拥有可以设置的属性x和对应的事件xChange时,解释[(x)]语法就容易多了。 下面的SizerComponent符合这个模式。它有size属性和伴随的sizeChange事件:

src/app/sizer.component.ts
content_copy
  1. import { Component, EventEmitter Input Output} from '@angular/core';
  2. @Component({
  3. selector:'app-sizer'`
  4. <div>
  5. <button (click)="dec()" title="smaller">-</button>
  6. <button (click)="inc()" title="bigger">+</button>
  7. <label [style.font-size.px]="size">FontSize: {{size}}px</label>
  8. </div>`
  9. })
  10. exportclass SizerComponent{
  11. @Input() size number |string;
  12. @Output sizeChange =new EventEmitter<number>();
  13. dec.resize(-1);}
  14. inc(+}
  15. resize(delta number){
  16. size Mathmin(40max8++ delta));
  17. sizeChangeemitsize);
  18. }
  19. }

size的初始值是一个输入值,来自属性绑定。(译注:注意size前面的@Input) 点击按钮,在最小/最大值范围限制内增加或者减少size。 然后用调整后的size触发sizeChange事件。

下面的例子中,AppComponent.fontSize被双向绑定到SizerComponent

src/app/app.component.html (two-way-1)
content_copy<app-sizer [(size)]"fontSizePx"></app-sizer> px]>Resizable TextSizerComponent.size初始值是AppComponent.fontSizePx。 点击按钮时,通过双向绑定更新AppComponent.fontSizePx。 被修改的AppComponent.fontSizePx通过样式绑定,改变文本的显示大小。

双向绑定语法实际上是属性绑定和事件绑定的语法糖。 Angular将SizerComponent的绑定分解成这样:

src/app/app.component.html (two-way-2)
content_copy<app-sizer [size]"fontSizePx" (sizeChange)"fontSizePx=$event"></app-sizer>

$event变量包含了SizerComponent.sizeChange事件的荷载。 当用户点击按钮时,Angular 将$event赋值给AppComponent.fontSizePx

显然,比起单独绑定属性和事件,双向数据绑定语法显得非常方便。

我们希望能在像<input><select>这样的 HTML 元素上使用双向数据绑定。 可惜,原生 HTML 元素不遵循x值和xChange事件的模式。

幸运的是,Angular 以NgModel指令为桥梁,允许在表单元素上使用双向数据绑定。


内置指令

上一版本的 Angular 中包含了超过 70 个内置指令。 社区贡献了更多,这还没算为内部应用而创建的无数私有指令。

在新版的 Angular 中不需要那么多指令。 使用更强大、更富有表现力的 Angular 绑定系统,其实可以达到同样的效果。 如果能用简单的绑定达到目的,为什么还要创建指令来处理点击事件呢?

src/app/app.component.html
content_copy我们仍然可以从简化复杂任务的指令中获益。 Angular 发布时仍然带有内置指令,只是没那么多了。 我们仍会写自己的指令,只是没那么多了。

下面来看一下那些最常用的内置指令。它们可分为属性型指令或结构型指令。


内置属性型指令

属性型指令会监听和修改其它HTML元素或组件的行为、元素属性(Attribute)、DOM属性(Property)。 它们通常会作为HTML属性的名称而应用在元素上。

更多的细节参见属性型指令一章。 很多Angular模块,比如RouterModule和FormsModule都定义了自己的属性型指令。 本节将会介绍几个最常用的属性型指令:

  • NgClass- 添加或移除一组CSS类

  • NgStyle- 添加或移除一组CSS样式

  • NgModel- 双向绑定到HTML表单元素


NgClass 指令

我们经常用动态添加或删除 CSS 类的方式来控制元素如何显示。 通过绑定到NgClass,可以同时添加或移除多个类。

CSS 类绑定是添加或删除单个类的最佳途径。

src/app/app.component.html
content_copy当想要同时添加或移除多个CSS 类时,NgClass指令可能是更好的选择。

试试把ngClass绑定到一个 key:value 形式的控制对象。这个对象中的每个 key 都是一个 CSS 类名,如果它的 value 是true,这个类就会被加上,否则就会被移除。

组件方法setCurrentClasses可以把组件的属性currentClasses设置为一个对象,它将会根据三个其它组件的状态为truefalse而添加或移除三个类。

src/app/app.component.ts
content_copycurrentClasses: {}; setCurrentClasses{ // CSS classes: added/removed per current state of component properties .currentClasses = { 'saveable': .canSave 'modified'!.isUnchanged'special'.isSpecial }; NgClass属性绑定到currentClasses,根据它来设置此元素的CSS类:

src/app/app.component.html
content_copy<div [ngClass]"currentClasses">This div is initially saveable,unchanged,and special 
  

你既可以在初始化时调用setCurrentClassess(),也可以在所依赖的属性变化时调用。


NgStyle 指令

我们可以根据组件的状态动态设置内联样式。NgStyle绑定可以同时设置多个内联样式。

样式绑定是设置单一样式值的简单方式。

src/app/app.component.html
content_copyfont-size]"isSpecial ? 'x-large' : 'smaller'" > This div is x-large or smaller. 如果要同时设置多个内联样式,NgStyle指令可能是更好的选择。

NgStyle需要绑定到一个 key:value 控制对象。 对象的每个 key 是样式名,它的 value 是能用于这个样式的任何值。

来看看组件的setCurrentStyles方法,它会根据另外三个属性的状态把组件的currentStyles属性设置为一个定义了三个样式的对象:

src/app/app.component.ts
content_copycurrentStyles{}; setCurrentStyles// CSS styles: set per current state of component properties .currentStyles 'font-style'.canSave ? 'italic' 'normal''font-weight'.isUnchanged 'bold' 'font-size''24px' '12px' NgStyle属性绑定到currentStyles,以据此设置此元素的样式:

src/app/app.component.html
content_copy<div [ngStyle]"currentStyles"> This div is initially italic,normal weight,and extra large (24px). setCurrentStyles(),也可以在所依赖的属性变化时调用。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读