diff --git a/src/ast/renderer-ast-dfn.ts b/src/ast/renderer-ast-dfn.ts index 0570381a..d9fb2bb6 100644 --- a/src/ast/renderer-ast-dfn.ts +++ b/src/ast/renderer-ast-dfn.ts @@ -58,6 +58,7 @@ export enum SyntaxKind { RegexpReplace = 28, JSONStringify = 29, HelperCall = 30, + GetRootCtxCall = 31, ComponentReferenceLiteral = 32, SlotRendererDefinition = 33, SlotRenderCall = 34, @@ -72,7 +73,7 @@ export enum SyntaxKind { export type Expression = Identifier | FunctionDefinition | Literal | BinaryExpression | UnaryExpression | CreateComponentInstance | NewExpression | MapLiteral | ComponentRendererReference | FunctionCall | Null | Undefined | MapAssign | ArrayIncludes | ConditionalExpression | FilterCall | HelperCall | EncodeURIComponent | - ArrayLiteral | RegexpReplace | JSONStringify | ComputedCall | ComponentReferenceLiteral | + ArrayLiteral | RegexpReplace | JSONStringify | ComputedCall | GetRootCtxCall | ComponentReferenceLiteral | SlotRendererDefinition | SlotRenderCall | ComponentClassReference | CreateComponentPrototype | Typeof export type Statement = ReturnStatement | ImportHelper | VariableDefinition | AssignmentStatement | If | ElseIf | Else | @@ -85,7 +86,7 @@ export type UnaryOperator = '!' | '~' | '+' | '()' | '-' export class ArrayLiteral implements SyntaxNode { public readonly kind = SyntaxKind.ArrayLiteral constructor ( - public items: [Expression, boolean][] // [item, isSpread] + public items: [Expression, boolean][] ) {} } @@ -306,6 +307,13 @@ export class FilterCall implements SyntaxNode { ) {} } +export class GetRootCtxCall implements SyntaxNode { + public readonly kind = SyntaxKind.GetRootCtxCall + constructor ( + public args: Expression[] + ) {} +} + export class HelperCall implements SyntaxNode { public readonly kind = SyntaxKind.HelperCall constructor ( diff --git a/src/ast/renderer-ast-walker.ts b/src/ast/renderer-ast-walker.ts index 153b821f..cbe7fb47 100644 --- a/src/ast/renderer-ast-walker.ts +++ b/src/ast/renderer-ast-walker.ts @@ -48,6 +48,7 @@ export function * walk (node: Expression | Statement): Iterable & ComponentDefineOptions) return instance } +function getRootCtx (ctx: T) { + let last = ctx + while (ctx.parentCtx) { + last = ctx + ctx = ctx.parentCtx + } + + // 如果跟组件 render 调用的时候传递了 parentCtx,会找到这个对象 + // 通过 ctx 是否有 data 来判断是不是真正的 rootCtx + // @ts-ignore + return ctx.data ? ctx : last +} + function handleError (e: Error, instance: Component<{}>, info: string) { let current: Component<{}> | undefined = instance while (current) { @@ -221,6 +234,7 @@ export const _ = { xstyleFilter, xclassFilter, createFromPrototype, + getRootCtx, iterate, callFilter, callComputed, diff --git a/src/target-js/js-emitter.ts b/src/target-js/js-emitter.ts index 12548b8c..f51a28ea 100644 --- a/src/target-js/js-emitter.ts +++ b/src/target-js/js-emitter.ts @@ -90,6 +90,11 @@ export class JSEmitter extends Emitter { this.writeExpressionList(node.args) this.write(')') break + case SyntaxKind.GetRootCtxCall: + this.write('_.getRootCtx(') + this.writeExpressionList(node.args) + this.write(')') + break case SyntaxKind.HelperCall: this.write(`_.${node.name}(`) this.writeExpressionList(node.args)