我创建了一个带上下文的结构指令。
var object = {
propriety1 : "value1",
propriety2 : "value2",
propriety3 : "value3"
}
for (var x in object) {
console.log(object.x);
}
console.log(object.propriety1);
这就是我使用它的方式。
@Directive({selector: '[myDir]'})
export class MyDir implements OnInit {
constructor(private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef,
) { }
public context = {$implicit: false}
ngOnInit() {
this.viewContainerRef.createEmbeddedView(this.templateRef, this.context)
}
}
模板已正确安装到视图中,<pre *myDir="let context">Context: {{ context | json}}</pre>
按预期存在。
但是,如果我尝试更改上下文,则不会反映在视图中。从ngTemplateOutlet
spec from the Angular repo来看,看起来应该在上下文发生变化时进行更新。 我的代码中是否有错误,或者我是否误解了规范?
我也试过注入CR并手动触发变化检测,但它没有用。在我的实际情况中,更改应该是在可观察的订阅上触发,该订阅会监听鼠标事件,但这是一个简单间隔的演示。
Context: false
虽然Observable
.interval(500)
.map((_, i) => i % 2 == 0)
.takeUntil(this.destroy$)
.subscribe(context => {
this.context = {$implicit: context}
console.log('Context is now', this.context.$implicit)
})
确实更改,并且控制台中显示的更改 ,但视图不会更新。 Here's a demo on StackBlitz
我已经添加取消订阅销毁,因为否则闪电战在一些重新加载后发疯。还添加了一个测试observable,它只是一个与AppComponent间隔半秒的简单计数器,与指令无关。这只是一个完整性检查应用程序正在运行,CD循环通常正在整个应用程序正常运行。我不在任何地方使用OnPush。
答案 0 :(得分:3)
Javascript是非常引人入胜的语言。
让我们考虑以下代码:
let view: any = {};
function detectChanges() {
console.log(view.context);
}
function createEmbeddedView(context) {
view.context = context;
}
let context = { x: false };
createEmbeddedView(context);
detectChanges(); // prints { x: false }
当我们创建context
并将其传递给createEmbeddedView
函数时。
现在让我们改变context
。我们将做两个选择:
1)改变自己
context = { x: true };
detectChanges(); // prints { x: false }
2)更改INTERNALS
context.x = true;
detectChanges(); // prints { x: true} Hooray!!!
我们可以看到我们的输出在第一种情况下没有改变,而在第二种情况下工作。这是因为在javascript中我们传递了对象by sharing。
它是一种特定的传值。如果我们更改参数本身,它将不会对函数内部的项目产生任何影响。但是如果我们改变一些属性,那么它将改变项目。
因此,对于您的情况,您可以更改您的上下文,如:
this.context.$implicit = context;
https://stackblitz.com/edit/so-context-question-a4n5yx?file=app%2Fapp.component.ts