Как разрешить вводимые экземпляры в Vue.js с использованием TypeScript


Согласно официальному документу , кажется, что мы можем использовать функцию внедрения зависимостей, пока мы остаемся на объектно-ориентированной структуре.

Вот мой вопрос. Я использую TypeScript для достижения этой цели (на основе класса). Я собираюсь использовать Inversify как контейнер МОК. Моя первоначальная идея была примерно такой:

DependencyConfig.ts:

import { Container } from "inversify";
import "reflect-metadata";
import Warrior from "./interfaces/Warrior";
import { Ninja } from "./models/Warrior";

let container = new Container();

container.bind<Warrior>(Symbol("Warrior")).to(Ninja);

export default container;

App.ts:

import container from "./DependencyConfig";

@Component({
  name: "App",
  provide: container
})
export default class App extends Vue {
}

Когда я зарегистрировался в консоли разработчика моего браузера, я смог увидеть container было установлено в поле _provided. Вот Hello.ts, дочерний компонент App.ts:

Hello.ts:

@Component({
  name: "Hello",
  inject: [ "container" ]
})
export default class Hello extends Vue {
  created (): void {
    console.log(this);
  }
}

Поскольку App.ts может обращаться к Hello.ts через vue-router, он не регистрируется Hello.ts как дочерний компонент. Я ожидал, что введенный контейнер должен появиться на _injected или что-то подобное. Однако я не смог его найти. Я изменил значение свойства inject с "container" на { "container": Symbol("Container") }, но так и не смог его найти.

Service Locator :

Это работает хорошо использовать сервис-локатор вместо пары provide/inject:

// App.ts
@Component({
  name: "App"
})
export default class App extends Vue {
}

// Hello.ts
import container from "./DependencyConfig";

@Component({
  name: "Hello"
})
export default class Hello extends Vue {
  created (): void {
    var ninja = container.get<Ninja>(Symbol("Warrior"));
    console.log(ninja.name);
  }
}

Тем не менее, я хочу избежать использования шаблона Service locator здесь. Я что-то пропустил при использовании пары provide/inject для инъекции зависимостей?

1 3

1 ответ:

Я нашел решение. Если мы используем vue-class-component и еще vue-property-decorator, мы можем достичь этой цели-используя provide/inject пара. Вот мой фрагмент кода:

// App.vue
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import SERVICE_IDENTIFIER from "./models/Identifiers";
import container from "./configs/DependencyConfigs";

@Component({
  name: "App",
  // Provides IoC container at the top level of VueComponent
  provide: {
    [SERVICE_IDENTIFIER.CONTAINER]: container
  }
})
export default class App extends Vue {
}
</script>

В самом верхнем компоненте Vue, App.vue, мы предоставляем экземпляр container так, чтобы его все дочерние компоненты могли использовать его. Вот один из его дочерних компонентов, Ninja.vue:

// Ninja.vue
<script lang="ts">
import Vue from "vue";

// Imports both Component and Inject decorators from vue-property-decorator,
// instead of vue-class-component
import { Component, Inject } from "vue-property-decorator";

import { Container } from "inversify";

import SERVICE_IDENTIFIER from "../models/Identifiers";
import { Ninja as _Ninja } from "../models/Warrior";

@Component({
  name: "Ninja"
})
export default class Ninja extends Vue {
  public warrior: string;
  public weapon: string;

  // IoC container provided from App.ts is injected here
  @Inject(SERVICE_IDENTIFIER.CONTAINER)
  private _container: Container;

  private _ninja: _Ninja;

  created (): void {
    this._ninja = this._container.get<_Ninja>(SERVICE_IDENTIFIER.WARRIOR);
    this.warrior = this._ninja.name;
    this.weapon = this._ninja.weapon.name;
  }
}
</script>

Дочерний компонент использует декоратор @Inject(Symbol) для разрешения введенного экземпляра container из App.vue.

Я написал об этом сообщение в блоге в ианглийский икорейский об этом.

HTH