自定义元素的绑定上下文 - 它到底是什么,如何访问父虚拟机 [英] Custom element's Binding Context - what is it exactly, how to access parent VM

查看:55
本文介绍了自定义元素的绑定上下文 - 它到底是什么,如何访问父虚拟机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I couldn't find the answer in the docs, so I'm asking here. What exactly is the binding context passed to the bind method of custom element. Is it simply equal to router's currently active ViewModel? At least, that's what I've found out so far.

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

Why isn't it the element's parent (in the terms of 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>

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

the output in the console is just current viewmodel (Welcome) printed twice.

我希望第一个(外部)的欢迎 code> myelem ,但 MyElem 第二次(内部)出现......

I'd expect it to be Welcome for the first (outer) myelem, but MyElem for the second (inner) occurance...

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

Please explain why am I wrong here, and how can the inner custom element be aware of it's actual context (by which I mean the outer one in the case above), without using ugly hacks like creating secret property in the "shared" context (the one which actually gets passed to both of them)

推荐答案

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

In terms of data-binding, both elements are bound to the same binding context. Consider this example:

<div foo.bind="bar">
  <div foo.bind="bar"></div>
</div>

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

You would expect both <div> elements to have the same binding context right? Both element's foo property should be bound to the same model's bar property. The same holds true in this scenario:

<myelem foo.bind="bar">
  <myelem foo.bind="bar"></myelem>
</myelem>

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

Both instances of <myelem> are bound to the same binding context / model.

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

If I understand the question correctly, you would like an elegant way to give the inner MyElem class instance a reference to the outer MyElem class instance. Luckily, you're using Aurelia so there is a very nice way to do this... declare it as a dependency using the inject decorator:

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;
  }
  ...
}

但有一点需要注意...

There's one caveat however...

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

The Aurelia dependency-injection container's default behavior is to create an instance of the requested item if an instance is not found in the container. This means that @inject(Parent.of(MyElem)) is not quite what we want. In situations where there is no parent MyElem instance the container will create one for us instead of returning null. Normally we'd use @inject(Optional.of(MyElem)) to tell the container to give us the instance, only when it exists in the container. I don't know of a way to combine Parent.of and Optional.of. I'll create an issue in the aurelia dependency-injection repository so we can get this feature added.

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

In the meantime, we can easily create our own Resolver that combines the behavior of Parent.of and 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);
  }
}

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

So the new version of our MyElem class would look like this:

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;
  }
  ...
}

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

Here's a working example. Check the console for log messages showing the result:

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

这篇关于自定义元素的绑定上下文 - 它到底是什么,如何访问父虚拟机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆