要在视图模型中获取容器,通常有 3 个选项:
1。注入容器
使用 @inject(Container) 装饰您的视图模型或简单地应用 any 装饰器(这使得 tsc 发出类型元数据)并确保在您的构造函数中指定类型,如下所示:
constructor(private container: Container) {}
这是获取容器的推荐方法,因为它会为您提供范围为该特定视图模型的子容器。这意味着如果您请求 Element 或 Router 之类的内容,您还将获得该视图模型范围内的内容。
您注册到该容器的内容只能通过该容器或其子级解析,而不是其兄弟姐妹或父级。
2。使用全局容器
总有一个“根”容器,您可以通过Container.instance 静态属性访问代码中的任何位置。
这对于某些在正常 aurelia 生命周期之外存在的组件很有用,或者如果您确实需要根目录。你会想尽可能避免这种情况,因为它会导致意大利面条代码。
3。 “滥用”路由器
我不一定会推荐这个,但每个配置的路由器上总是有一个 .container 属性。这是作用域子路由器 - 如果您将它注入到视图模型的构造函数中,您会得到相同的子路由器。
一旦你引用了容器:
调用container.get(Foo),仅从该容器中获取Foo 的实例,或调用container.getAll(Foo) 以从该容器及其所有父容器中获取所有Foo 的列表,直到根.
生命周期和范围
有两种终身注册类型:
-
singleton 在容器的生命周期内提供相同的实例
-
transient 每次调用容器时都会提供一个新实例
singleton 的生命周期进一步取决于它所注册的容器的生命周期,在典型的子容器的情况下,是视图模型的生命周期。
API 表面的其他部分基本上只是singleton 或transient 的不同范围变体。
设置注册类型
这里有很多选项,我不会在这里一一介绍。与您相关的是直接容器 API:
container.register...(key, fn)
之后,当您调用container.get(key) 时,它将根据您刚刚设置的注册来解决依赖关系。您也可以在事后更改它 - 只会覆盖现有的解析器。
单例:container.registerSingleton(Foo)
实例(单例,但您提供实例):container.registerInstance(Foo, new Foo(new Bar()))
瞬态:container.registerTransient(Foo)
自定义函数:container.registerHandler(Foo, (container, key, resolver) => new Foo(container.get(Bar))(对于带有单例Bar 的瞬态Foo)
还有其他选项,但这些是最常用的。
关于key, fn 参数的最后一点说明:调用register(Foo) 等同于调用register(Foo, Foo)。如果您不想/没有对要调用的类名的引用,也可以说 register("foo", Foo)。
能够打开调试器并说出document.body.aurelia.container.get("foo") 是我个人觉得有时调试非常方便的东西:)