【问题标题】:direct binding to a property of property in Angular直接绑定到 Angular 中的属性
【发布时间】:2020-02-02 14:50:29
【问题描述】:

我有一个这样的模型:

export class Person{
name: string;
}

在我的组件中使用如下:

export class TestComponent {
  @Input() person : Person;
  constructor() {
  }
}

我想从 html 中设置人名如下:

<app-test [person.name]="'Jack'"</app-test>

当我这样做时,angular 会生气:“无法绑定到 'person.name',因为它不是 'app-test' 的已知属性。”

嗯,他是对的,人是我组件的属性,而不是 person.name

另一方面,我们在以下示例中没有收到任何错误:

<span [style.color]="'red'">This span is red.</span>

我是否违反了规则??

或者样式属性在内部是不同的?怎么样?

谢谢

【问题讨论】:

    标签: angular property-binding


    【解决方案1】:

    您不能绑定到 person.name,因为 Input() 装饰器绑定到子组件(测试)中的人员,而不是像 person.name 这样的任何特定属性

    您必须发送一个对象来解决此问题。

    看到这个example

    【讨论】:

      【解决方案2】:

      你是对的 [ngStyle] 不一样 [style] 不一样,你需要

      <app-test [person]="{name:'Jack'}"</app-test>
      

      其他选项是

      <app-test [person]="person"</app-test>
      

      在你的 main.app 中

      this.person.name='Jack'
      

      请记住,如果您在输入中使用对象,则在父项或子项中对对象属性的任何更改都会更改对象的“属性”

      【讨论】:

        【解决方案3】:

        这是因为您尝试传递给测试组件的 Input 属性是“person.name”,它没有在您的测试组件上定义。您的测试组件需要一个名为“人”的东西。其次,您传递的是一个字符串,而不是您在测试组件上定义的 Person 类型。更改 Test 组件以接受字符串或传递 Person 并引用 Test 组件中的 name 属性。 并确保名称匹配

        您可以考虑将人名传递给其他组件的两种方式

        &lt;app-test [name]="person.name" [person]="person"&gt;&lt;/app-test&gt;

        然后在测试组件中:

         export class TestComponent  {
          @Input() name: string;
          @Input() person : Person;
        }
        

        注意名称和类型如何匹配?我的建议是不要超过你需要的。如果您只需要传递人名,只需让您的组件接受一个字符串。无需传递整个对象。

        TestComponent 模板:

        <h1>Person: {{person.name}}</h1>
        <h1>Name: {{name}}</h1>
        

        我将添加一个指向 Angular 文档的链接,因为我认为它是 Angular 的一个非常重要的部分,您可能想要查看它。他们的英雄教程非常好。

        https://angular.io/api/core/Input

        【讨论】:

        • 你是对的。但是假设我的测试组件有 10 个其他子组件,它们有自己的属性和默认值。例如,两个输入组件具有以下属性: required、placeholder、type(password) 、 autocomplete 等......如果我在我的测试组件中定义了 input1placeholder、input2placeholder 等属性,它会变得非常混乱。我坚持喜欢 [style.color] 的原因是整洁,代码更少,避免设置默认值。假设我正在为自己编写一个组件框架,并且想要更少的限制和更少的代码。
        • 嗯 [name]="person.name" 是你想要做的。子组件只会传递字符串。他们不再需要引用,因为父组件拥有它。我会研究的另一个选项是 Observable Data Services。它是您可以在 Angular 中使用的模式。如果您打算将对象或值向下传递到像 10 个孩子这样的长组件树,我不建议使用输入属性。使用 DI,您可以简单地使用服务来获取和更新值。它更清洁。 blog.angular-university.io/…
        【解决方案4】:

        这是因为style 是带有多个选择器和输入的指令。

        您可以通过一些可以完成这项工作的指令来实现这一点。我想你可以做类似这样的事情: (未测试)

        import { Directive, ViewContainerRef, ChangeDetectorRef, OnInit } from '@angular/core';
        
        const selector = `
          [name],
          [name.foo],
          [name.bar]
        `;
        
        export const inputs = [
          'name',
          'name.foo',
          'name.bar'
        ];
        
        
        
        @Directive({
          selector,
          inputs
        })
        export class HelloDirective implements OnInit {
          constructor(
            private viewContainerRef: ViewContainerRef
          ) {
          }
        
          ngOnInit(): void {
            const getSetKeys = Object.keys(this).filter(item => inputs.indexOf(item) > -1);
            const getValues = getSetKeys.map(item => this[item]);
            const component = this.viewContainerRef['_view'].component;
            getSetKeys.forEach((item, index) => {
              const splitKey = item.split('.');
              component[splitKey[0]][splitKey[1]] = getValues[index];
            })
          }
        }
        

        在这种情况下,您可以将指令用作 &lt;some-component [name.foo]="'Some foo'" [name.bar]="'Some bar'"&gt;&lt;/some-component&gt; 这将注入组件中的“名称”对象。

        我不推荐这种方式,但可以实现它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-14
          • 1970-01-01
          • 1970-01-01
          • 2017-11-29
          • 1970-01-01
          相关资源
          最近更新 更多