I don't understand.. if I can use import
in Aurelia, why do I have to wire up the constructor with @autoinject()
and all that? I'm sure I'm missing something, but, from what I can tell, I can just use my imported module whenever I want.
import something from "whatever"
export class SomeViewModel {
activate() {
// use something
}
}
Typically, in an Aurelia application, the thing you are import
ing isn't an instance of Something
it's the class Something
. To actually use whatever has been import
ed, you need an instance of it.
import Something from 'whatever';
let something = new Something();
When you use Aurelia's Dependency Injection system, you are utilizing a design pattern called "Inversion of Control." Instead of your class (or you) being in charge of instantiating its dependencies, it lists what dependencies it has and then has instances of the dependencies injected in to its constructor function.
This helps with testability, as now you can pass mocked instances of the dependencies to a class in your test fixtures (note that in your tests, your tests will pass the mocks to the constructor, and not rely on Aurelia's DI container).This also allows you to tap in to the Dependency Injection container's ability to be configured to create dependencies using different object lifestyles such as singletons and transient.
--- Edits to answer OP's questions from comments ---
If I import a module defined as export default class Something into an
aurelia view model using constructor injection, it does not need to be
instantiated. It is an instance of the class Something.
This is because Aurelia's Dependency Injection container is instantiating an instance for you. This is why your code looks like this:
import {inject} from 'aurelia-framework';
import Something from 'somewhere';
@inject(Something)
export class Foo {
constructor(something) {
this.something = something;
}
//...
}
and not
import Something from 'somewhere';
export class Foo {
constructor(Something) {
this.something = something;
}
//...
}
You are telling Aurelia "I need one of these, please give it to me," and Aurelia says "Sure thing, I've created one or I already had one lying around, here it is."
In other words, it appears that aurelia's constructor DI only works
with class exports, and it does instantiate the class. It looks like
if I want to import something like moment js into my aurelia view
model, I should just continue doing things the way I've always done
them (not using aurelia's DI). Does that sound correct?
This is correct. Libraries like moment
give you a function to use, and not a class that can be instantiated by Aurelia. For these you would continue to use them as in the past.
Well technically you can use the imported modules without Aurelia's DI, but in most situations that would be a bad thing. The Dependency Injection layer gives you so much versatility and flexibility. It handles caching, it supports singleton and transient dependencies, handles lifetime and makes thing neater from an architectural perspective.