如何在我们的自定义指令中以角度解码现有的结构指令字符串语法

Posted

技术标签:

【中文标题】如何在我们的自定义指令中以角度解码现有的结构指令字符串语法【英文标题】:How to decode existing structural directive string syntax in our custom directive in angular 【发布时间】:2021-11-01 12:34:36 【问题描述】:

就像我说的,我想在自定义指令中使用现有的基于结构指令字符串的语法

<element *ngFor='let x of array;let last = last;'></element>

我没有找到任何详细的文档,我们如何在自定义结构指令中解码上述语法。我知道我们可以将此语法与所有结构指令 *xyz 一起使用,但我总是使用 [xyz] 代替。我尝试查找 Angular 官方文档,但一无所获。

所以我进入他们的代码以了解*NgFor in github,除了他们如何解码语法之外,我得到了一切。

如果您看到选择器,如下所示

@Directive(selector: '[ngFor][ngForOf]')

@Input()
set ngForTrackBy(fn: TrackByFunction<T>) 
    //definition

所有输入方法都以 ngForTrackBy 之类的选择器前缀开头。只有这样吗?我们必须遵循选择器前缀吗? 如果是,那么我们可以用这种基于前缀的方法做些什么?如果不是,那么正确的方法是什么?

【问题讨论】:

【参考方案1】:

编译器的工作是匹配使用let 语法定义的变量和传递到嵌入视图的上下文。您可以定义任意数量的变量,但如果您不通过上下文传递它们的值,它们的值将是未定义的。

在这里,我使用自定义 my 指令并使用 let 语法定义两个变量 ab

<ng-template my let-a=a let-b=b let-c=c>
  <span>inside my, a is a, b is b, c is undefined: c === undefined</span>
</ng-template>

然后在描述指令时,我将带有变量值的上下文传递给嵌入式视图:

import  Directive, TemplateRef, ViewContainerRef  from '@angular/core';

@Directive(
  selector: '[my]'
)
export class MyDirective 
  constructor(public vc: ViewContainerRef, public t: TemplateRef<any>) 
  

  ngOnInit() 
    const t = this.vc.createEmbeddedView(this.t, a: 3, b: 4);
  

ngForOf 指令也是如此,here's how the context 会查找它:

export class NgForOfContext<T, U extends NgIterable<T> = NgIterable<T>> 
  constructor(public $implicit: T, public ngForOf: U, public index: number, public count: number) 

  get first(): boolean 
    return this.index === 0;
  

  get last(): boolean 
    return this.index === this.count - 1;
  

  get even(): boolean 
    return this.index % 2 === 0;
  

  get odd(): boolean 
    return !this.even;
  

您还可以使用带有自定义指令的简写语法:

<span *my="let a=a; let b=b; let c=c;">inside my, a is a, b is b, c is undefined: c === undefined</span>

【讨论】:

好的,所以我们将在编写指令时考虑模板以使用简写语法。还有一件事要确认 - 使用 ngForOf 看起来我们必须使用带有指令输入的前缀作为编译器添加前缀,同时将简写语法转换为 ng-template。例如:如果我希望 of 作为指令中的输入,那么它将是 myOf 作为输入 不是真的,这也可以&lt;span *my="let a=a; let b=b; let c=c;"&gt;inside my, a is a, b is b, c is undefined: c === undefined&lt;/span&gt;ngFor 支持两个名称 @Directive(selector: '[ngFor][ngForOf]') github.com/angular/angular/blob/… 请纠正我,let a=a; let b=b; let c=c; 正在将数据从指令分配给 html,而不是相反。就像如果我们需要使用相同的语法将指令内部的数据(数组)作为输入传递,那么我们需要方法名称中的前缀,例如 ngForOf 的情况,它是 oftrackBy跨度> &lt;li *ngFor="let item of items; index as i; trackBy: trackByFn"&gt;...&lt;/li&gt; 转换成这个&lt;ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn"&gt; &lt;li&gt; &lt;/li&gt; &lt;/ng-template&gt; 对吧? finally found this in docs, I think they update it recently 解析器将 PascalCase 应用于所有指令,并在它们前面加上指令的属性名称,例如 ngFor。例如,ngFor 输入属性 of 和 trackBy 映射到 ngForOf 和 ngForTrackBy。当 NgFor 指令在列表中循环时,它设置和重置它自己的上下文对象的属性。这些属性可以包括但不限于 index、odd 和一个名为 $implicit 的特殊属性

以上是关于如何在我们的自定义指令中以角度解码现有的结构指令字符串语法的主要内容,如果未能解决你的问题,请参考以下文章

如何模拟具有要求字段的角度指令

详解Vue中的自定义指令

自定义指令按钮单击的控制器方法?角度js

6.5 分支指令的控制信号

Vue:八种实用的自定义指令

Vue2.x Todo之自定义指令实现自动聚焦的方法