Angular如何处理[class.example]的绑定=" true"?

时间:2017-07-08 03:56:31

标签: angular

您可以使用CSS类和样式进行这些特殊的模板绑定。

它们看起来像这样:

<div [class.example]="true"
     [style.width.px]="100">
</div>

我查看了ngClassngStyle指令,但无法弄清楚它们是如何工作的。

我想知道我是否可以将这种语法与我自己的组件一起使用。

例如:

<my-component [name.first]="John" [name.last]="Smith></my-component>

使用这样的代码:

@Component({..})
export class MyComponent {
    @Input()
    public name: any;
}

我希望angular会将{first:"John",last:"Smith"}之类的内容传递给name输入,但我只是收到一条错误消息,指出name.firstname.last输入不是t存在于组件上。

有没有办法让上述工作像[class.any-thing-here]那样工作?

1 个答案:

答案 0 :(得分:3)

这些绑定是一种特殊情况BoundElementPropertyAst Live example

PropertyBindingType.Class
PropertyBindingType.Style

Angular在https://github.com/angular/angular/blob/4.2.x/packages/compiler/src/template_parser/binding_parser.ts#L244-L298

中解析它

<强> binding_parser.ts

const ATTRIBUTE_PREFIX = 'attr';
const CLASS_PREFIX = 'class';
const STYLE_PREFIX = 'style';

createElementPropertyAst(elementSelector: string, boundProp: BoundProperty):
    BoundElementPropertyAst {
  if (boundProp.isAnimation) {
    return new BoundElementPropertyAst(
        boundProp.name, PropertyBindingType.Animation, SecurityContext.NONE, boundProp.expression,
        null, boundProp.sourceSpan);
  }

  let unit: string|null = null;
  let bindingType: PropertyBindingType = undefined !;
  let boundPropertyName: string|null = null;
  const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
  let securityContexts: SecurityContext[] = undefined !;

  // Check check for special cases (prefix style, attr, class)
  if (parts.length > 1) {
    if (parts[0] == ATTRIBUTE_PREFIX) {
      boundPropertyName = parts[1];
      this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
      securityContexts = calcPossibleSecurityContexts(
          this._schemaRegistry, elementSelector, boundPropertyName, true);

      const nsSeparatorIdx = boundPropertyName.indexOf(':');
      if (nsSeparatorIdx > -1) {
        const ns = boundPropertyName.substring(0, nsSeparatorIdx);
        const name = boundPropertyName.substring(nsSeparatorIdx + 1);
        boundPropertyName = mergeNsAndName(ns, name);
      }

      bindingType = PropertyBindingType.Attribute;
    } else if (parts[0] == CLASS_PREFIX) {
      boundPropertyName = parts[1];
      bindingType = PropertyBindingType.Class;
      securityContexts = [SecurityContext.NONE];
    } else if (parts[0] == STYLE_PREFIX) {
      unit = parts.length > 2 ? parts[2] : null;
      boundPropertyName = parts[1];
      bindingType = PropertyBindingType.Style;
      securityContexts = [SecurityContext.STYLE];
    }
  }

  // If not a special case, use the full property name
  if (boundPropertyName === null) {
    boundPropertyName = this._schemaRegistry.getMappedPropName(boundProp.name);
    securityContexts = calcPossibleSecurityContexts(
        this._schemaRegistry, elementSelector, boundPropertyName, false);
    bindingType = PropertyBindingType.Property;
    this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, false);
  }

  return new BoundElementPropertyAst(
      boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit,
      boundProp.sourceSpan);
}

它们与任何@Input内置指令都没有任何联系。它们只是元素的绑定。

当angular创建视图时,它使用这些绑定来应用于元素

return jit_viewDef1(0,[(_l()(),jit_elementDef2(0,null,null,1,'div',[],[[2,'example',
      null],[4,'width','px']],null,null,null,null)),(_l()(),jit_textDef3(null,['\n'])),
      (_l()(),jit_textDef3(null,['\n']))],null,function(_ck,_v) {
    var currVal_0 = true;
    var currVal_1 = 100;
    _ck(_v,0,0,currVal_0,currVal_1);
});

请看上面的elementDef。此函数采用绑定参数:

function elementDef(................................bindings...
                                                       \/
jit_elementDef2(0,null,null,1,'div',[],[[2,'example', null],4,'width','px']]

[class.any-thing-here]绑定不能满足您的需求。 ngClassngStyle执行此操作。但是如果你看看他们的实现

[ngStyle]="{'font-style': styleExp}"
[ngClass]="{'first': true, 'second': true, 'third': false}"

你可以注意到这里没有魔力。他们可以拿一个物体。

因此,角度尊重[attr.x] [class.x] [style.x]但不会与[name.x]一起使用,因为期望name.x属性Plunker(请参阅控制台)