Angular结构型指令微语法的精确语法规则是什么?
Great question! Angular's microsyntax for structural directives is incredibly powerful but feels underdocumented when you want more than just basic *ngIf/*ngFor examples. Let's break down the precise, formal grammar rules, building on how the framework parses and desugars these expressions.
Core Desugaring Basics
First, remember that any structural directive using the * shorthand gets desugared into an <ng-template> with explicit input bindings. For example:
<p *ngIf="user as currentUser"></p>
Becomes:
<ng-template [ngIf]="user" [ngIfAs]="currentUser"> <p></p> </ng-template>
The microsyntax is just a concise way to define multiple input bindings and template context variables in one line.
Full Microsyntax Grammar Rules
The microsyntax is a sequence of clauses separated by semicolons (;). Each clause maps to either a template context variable or a directive input binding. Here's the breakdown of each clause type:
1. Variable Declaration (let Clause)
- Syntax:
let [variableName][=sourceExpression] - Purpose: Exposes a variable from the directive's template context to your template.
- If you omit
=sourceExpression, it defaults to binding to the context's$implicitproperty (e.g.,let itemin*ngForbinds to each iterated item). - If you include
=sourceExpression, it binds the variable to the named property in the directive's context (e.g.,let idx=indexin*ngForbinds to theindexproperty of the iteration context).
- If you omit
2. Value Aliasing (as Clause)
- Syntax:
[sourceExpression] as [aliasName] - Purpose: Does two things at once:
- Passes
sourceExpressionto the directive's primary input (the input with the same name as the directive, e.g.,ngIffor*ngIf). - Assigns the result of
sourceExpressionto thealiasNamevariable, making it available in the template.
- Passes
- This is exactly why
*ngIf="a as b"desugars to[ngIf]="a" [ngIfAs]="b".
3. Condition Filter (when Clause)
- Syntax:
when: [conditionExpression] - Purpose: Binds an additional conditional expression to a directive's
wheninput (common in custom structural directives, though not used in Angular's built-in ones). - Example:
*myDirective: when: isItemActivewould bind to the directive's@Input() when: boolean;property.
4. Iteration Binding (of Clause)
- Syntax:
let [variableName] of [iterableExpression] - Purpose: Specific to iteration directives like
*ngFor:- Binds
iterableExpressionto the directive's primary iteration input (e.g.,ngForOffor*ngFor). - Exposes
variableNameas the current item in the iteration (defaults to the$implicitcontext property).
- Binds
5. Explicit Input Binding (key=value Clause)
- Syntax:
[inputKey] = [expression](colon:is also allowed instead of=, e.g.,trackBy: myTrackFn) - Purpose: Directly binds to a named input property of the directive.
- Examples:
trackBy: trackById→ binds to[ngForTrackBy]="trackById"in*ngForindex = currentIndex→ binds to a custom directive's@Input() index: number;property
Clause Parsing Priority
Angular's microsyntax parser processes clauses in a specific order, which matters if there's ambiguity:
- First parses
asclauses (to handle primary input + variable aliasing) - Next parses
ofclauses (for iteration directives) - Then parses
whenclauses - Finally parses
letand explicitkey=valueclauses
Example Walkthrough
Let's parse the complex microsyntax example you mentioned:
let node; when: hasChild; a as b; let x of y; index = i; trackBy: f
Here's how it breaks down:
let node: Binds template variablenodeto the directive context's$implicitpropertywhen: hasChild: Binds to the directive'swheninput with thehasChildexpressiona as b: Passesato the directive's primary input, and assignsato template variableblet x of y: Bindsyto the directive's iteration input (e.g.,ngForOf), andxto each item in the iterationindex = i: Binds the directive'sindexinput to theiexpressiontrackBy: f: Binds the directive'strackByinput to theffunction
Final Note
If you want to dive into the exact parsing logic, Angular's MicrosyntaxParser class (part of the core framework) defines the full formal grammar. The docs don't spell this out explicitly, but understanding these rules lets you write custom structural directives with clean, concise microsyntax, or debug tricky binding issues with built-in directives.
内容的提问来源于stack exchange,提问作者keppla

