自定义元素的绑定上下文 - 它到底是什么,如何访问父虚拟机

mig*_*jek 7 javascript aurelia

我在文档中找不到答案,所以我在这里问.传递给bind自定义元素方法的绑定上下文究竟是什么?它仅仅等于路由器当前活动的ViewModel吗?至少,这是我到目前为止所发现的.

为什么它不是元素的父(在DOM方面)VM?

用这个代码

@customElement("myelem")
@inlineView("<template><content></content></template>")
export class MyElem{
    bind(ctx){
      console.log(ctx);
    }
}

// welcome.html
<myelem>
    <h3>inside myelem</h3>
    <myelem>
      <h4>inside inside ... </h4>
    </myelem>
  </myelem>
Run Code Online (Sandbox Code Playgroud)

控制台中的输出只是当前viewmodel(Welcome)打印两次.

我希望它是Welcome第一个(外部)myelem,但是MyElem第二个(内部)出现......

请解释为什么我在这里错了,内部自定义元素如何知道它的实际上下文(我的意思是上面的情况中的外部上下文),而不使用丑陋的黑客,比如在"共享"上下文中创建秘密属性(实际上传递给他们两个的那个)

Jer*_*yow 16

在数据绑定方面,两个元素都绑定到相同的绑定上下文.考虑这个例子:

<div foo.bind="bar">
  <div foo.bind="bar"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

您会期望两个<div>元素具有相同的绑定上下文吗?两个元素的foo属性应绑定到同一模型的bar属性.在这种情况下也是如此:

<myelem foo.bind="bar">
  <myelem foo.bind="bar"></myelem>
</myelem>
Run Code Online (Sandbox Code Playgroud)

两个实例<myelem>都绑定到相同的绑定上下文/模型.

如果我正确理解了这个问题,你想要一个优雅的方法来为内部MyElem类实例提供对外部MyElem类实例的引用.幸运的是,你正在使用Aurelia所以有一个非常好的方法来做这个...使用inject装饰器将它声明为依赖:

import {inject, Parent} from 'aurelia-dependency-injection';
import {customElement} from 'aurelia-framework';

@customElement("myelem")
@inject(Parent.of(MyElem))
export class MyElem {
  constructor(parent) {
    this.parent = parent;
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

但有一点需要注意......

Aurelia依赖注入容器的默认行为是,如果在容器中找不到实例,则创建所请求项的实例.这意味着这@inject(Parent.of(MyElem))不是我们想要的.在没有父MyElem实例的情况下,容器将为我们创建一个而不是返回null.通常我们会用它@inject(Optional.of(MyElem))来告诉容器给我们实例,只有它存在于容器中.我不知道将Parent.of和Optional.of结合起来的方法.我将在aurelia依赖注入存储库中创建一个问题,以便我们可以添加此功能.

在此期间,我们可以轻松创建自己的Resolver,它结合了Parent.of和Optional.of的行为:

import {resolver} from 'aurelia-dependency-injection';

@resolver()
export class OptionalParent {
  constructor(key) {
    this.key = key;
  }

  get(container) {
    if (container.parent && container.parent.hasResolver(this.key, false)) {
      return container.parent.get(this.key)
    }
    return null;
  }

  static of(key) {
    return new OptionalParent(key);
  }
}
Run Code Online (Sandbox Code Playgroud)

所以我们的MyElem类的新版本看起来像这样:

import {inject} from 'aurelia-dependency-injection';
import {customElement} from 'aurelia-framework';
import {OptionalParent} from './optional-parent';

@customElement("myelem")
@inject(OptionalParent.of(MyElem))
export class MyElem {
  constructor(parent) {
    this.parent = parent;
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

这是一个有效的例子.检查控制台是否有显示结果的日志消息:

https://gist.run/?id=1a84e0a466fb928aa075

  • 我已经更新了代码,以便在2015年11月Aurelia版本中使用依赖注入lib更改 (3认同)