【问题标题】:How to use Angular 2 extrapolation in html element attributes?如何在 html 元素属性中使用 Angular 2 外推?
【发布时间】:2016-07-06 02:15:07
【问题描述】:

我想将一些数据绑定到非自定义的 html 元素属性。但是,属性中的 {{ }} 不是外推的。 我将其他相关帖子视为“Angularjs templateUrl fails to bind attributes inside ng-repeat”,这是自定义指令的 angular 1 解决方案。

例如,我有:

size = 500;

我希望以下 SVG 元素正常工作:

<svg xmlns="http://www.w3.org/2000/svg/" width="{{size}}" height="{{size}}">
<rect width="{{size}}" height="{{size}}" fill="#DCB35C"/>
</svg>

我应该如何在 Angular 2 中做到这一点?

【问题讨论】:

    标签: javascript angularjs angular


    【解决方案1】:

    简答

    当 HTML 属性和 DOM 属性之间没有 1:1 映射时,必须使用 attribute binding syntax 否则 Angular 2 将报告“模板解析错误”。

    例子:

    • [attr.my-custom-attribute]="myComponentValue"
    • [attr.colspan]="1 + 1"

    在您的情况下,SVG 元素具有宽度和高度 DOM 属性,但它们不是您所期望的。它们是SVGAnimatedLength 对象。试图以旧方式设置它们的值不会做任何事情。这就是为什么您的模板不能按预期工作并且不报告错误的原因。切换到属性绑定语法将修复此行为:[attr.width]="width" [attr.height]="height"

    深入讲解

    属性绑定在 Angular 1 和 Angular 2 中的工作方式存在很大的概念差异。

    在 Angular 1 中,设置自定义属性如下所示:

    • &lt;div a-custom-attribute="I am a custom {{ 'attribute' }}"&gt;Text Content&lt;/div&gt;
    • &lt;div ng-attr-a-custom-attribute="I am a custom {{ 'attribute' }}"&gt;Text Content&lt;/div&gt; - this syntax 允许您绑定到原本会被浏览器急切处理的属性(例如 SVG 元素的 circle[cx] 属性、IMG 元素的 src 属性等)

    在 Angular 2 中,情况有所不同:

    Angular 2 引入了,正如他们所说的,a new mental model不是绑定到 HTML 属性,而是绑定到 DOM 属性。了解 the distinction between an HTML attribute and a DOM property 对于了解 Angular 2 绑定的工作原理至关重要。

    绑定到 DOM 属性可能如下所示:

    • &lt;img [src]="heroImageUrl"&gt;
    • &lt;img bind-src="heroImageUrl"&gt;
    • &lt;img src="{{ heroImageUrl }}"&gt; - 这可能看起来有点混乱,特别是如果某人有 AngularJS 1 背景,但 Angular 2 在渲染视图之前将这些插值转换为相应的属性绑定 (source)。 重要的是要记住,正如Mark 在评论部分指出的那样,在对插值进行评估后,其结果随后会转换为字符串(@ 987654328@)。这意味着此语法仅​​限于分配字符串值。

    请注意,如果名称无法匹配 DOM 属性,Angular 2 会报告“未知原生属性”错误:

    // Template parse errors:
    // Can't bind to 'colspan' since it isn't a known native property
    <tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
    
    // Template parse errors:
    // Can't bind to 'madeUpProperty' since it isn't a known native property
    <div [madeUpProperty]="My custom {{ 'madeUpProperty' }}"></div>
    

    这意味着当没有要绑定的 DOM 属性时,必须使用attribute binding syntax

    最后,我相信作为一个好的经验法则,当他想要修改时,应该始终使用property binding's syntax(例如[src]="heroImageUrl")来支持插值(例如src="{{heroImageUrl}}")元素的 DOM 属性,因为后者仅限于传递字符串值。另一个原因是,如果某人有 AngularJS 1 背景,这应该可以减少设置属性和 DOM 属性之间的混淆。

    【讨论】:

    • x="{{template_expression}}"[x]="template_expression" 之间存在细微差别——它们并不相同。使用{{}}template_expression 的结果转换为字符串,然后将其分配给属性x。使用[],没有字符串转换步骤。因此,我不同意 Angular 文档中声明“没有技术理由偏爱一种形式而不是另一种形式”。如果我们想为属性x分配字符串以外的东西,我们不能使用{{}},我们必须使用[]
    • @MarkRajcok 感谢您指出这一点。我已经编辑了我的答案。
    【解决方案2】:
    <svg xmlns="http://www.w3.org/2000/svg/" [attr.width.px]="size" [attr.height.px]="size">
      <rect [attr.width.px]="width" [attr.height.px]="height" fill="#DCB35C" />
    </svg>
    

    【讨论】:

    • .px 并不是真正需要的。这些是接受一个值的属性,然后它们在内部将 widthheight 应用于 svgrect 元素。看看this plunkr
    • 我只是通知px 在绘图时不需要svg developer.mozilla.org/en-US/docs/Web/SVG/Element/rect
    • 同意。请注意,我没有说它是必需的,但也不能那样使用。
    【解决方案3】:

    您应该使用属性绑定来绑定widthheight,方法是在绑定之前添加attr 前缀,例如[attr.*]

    标记

    <svg xmlns="http://www.w3.org/2000/svg/" [attr.width]="size" [attr.height]="size">
      <rect [attr.width]="width" [attr.height]="height" fill="#DCB35C" />
    </svg>
    

    import {Component} from 'angular2/core';
    import {bootstrap} from 'angular2/platform/browser';
    
    @Component({
      selector: 'demo-app',
      templateUrl: 'src/app.html',
      pipes: []
    })
    export class App {
      width: number = 100;
      height: number=100;
      size: number=100;
      constructor() { }
    }
    
    bootstrap(App);
    

    Demo Plunkr


    根据要求通过具有一些常量字符串值附加大小值,您只需将其放在attribute 上,如[attr.width]="size + '5'"

    <svg xmlns="http://www.w3.org/2000/svg/" [attr.width]="size" [attr.height]="size">
      <rect [attr.width]="width + '5'" [attr.height]="height + '5'" fill="#DCB35C" />
    </svg>
    

    Updated Plunkr

    【讨论】:

    • thx,如果我想让 width="{{size}}1" 将 1 附加到 size 字符串怎么办?
    • @lys1030 查看更新后的答案。它也有演示 plunkr。如果你想将宽度增加一倍,那么请执行[attr.width]="size+1"
    • 我的意思不是“加 1”,而是“追加 1”。例如,如果 size = 10,我想附加一个 5,得到 105。
    • 然后将其大小保持为字符串而不是数字
    • 谢谢!你和 Cosmin 都给出了很好的答案。我在犹豫要接受哪一个。在我决定之前,我会等几天看看投票结果。
    猜你喜欢
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 2023-04-03
    • 2016-10-26
    • 2018-11-25
    • 1970-01-01
    相关资源
    最近更新 更多