Better InversifyJS integration

It was interesting to discover the SL pattern, but, as we've seen, it isn't ideal. As a matter of fact, there are better ways for us to integrate InversifyJS.

As we've already discussed, the main issue of integrating InversifyJS and Vue.js is the fact that Vue handles the construction of the class instances, making it impossible for us to use constructor injection, and forcing us to use definite assignment assertions.

Let's discover and use the inversify-inject-decorators library (https://github.com/inversify/inversify-inject-decorators). This library provides a set of decorators that add support for lazy injection of InversifyJS-managed dependencies. With it, we will be able to declare our dependencies through decorators instead of having to retrieve them programmatically through a service locator. This library will take care of doing the lookup for us in the IoC container and inject the necessary dependencies.

Let's see how this works:

You can find the source code for this example in the code samples for this book under Chapter09/08-vue-injection-inversify-improved. If you wish to follow along, then just make a copy of the previous project (that is, Chapter09/07-vue-injection-inversify).
  1. The first thing we need to do is add the library to our dependencies:
npm install inversify-inject-decorators

As usual, you can use either npm or yarn, depending on what you prefer.

We didn't specify --save here because npm does this automatically.
  1. Next, we can remove everything related to InversifyJS from our App.vue file as we won't be using the SL pattern anymore:
<template> 
    <div id="app"> 
        <DriverSFC /> 
    </div> 
</template> 
 
<script lang="ts"> 
    import {Component, Vue} from 'vue-property-decorator'; 
    import DriverSFC from '@/components/DriverSFC.vue'; 
 
    @Component({ 
        components: { 
            DriverSFC, 
        }, 
    }) 
    export default class App extends Vue { 
    } 
</script> 
 
<style> 
</style> 
  1. Finally, we can update our DriverSFC.vue file, as follows:
<template> 
    <div class="hello"> 
        <h1>{{ driver }}</h1> 
    </div> 
</template> 
 
<script lang="ts"> 
    import {Component, Vue} from 'vue-property-decorator'; 
    import {Driver} from '../domain/driver'; 
    import {TYPES} from '@/ioc-types'; 
    import {container} from '../ioc-config'; 
    import getDecorators from 'inversify-inject-decorators'; 
 
    const { lazyInject } = getDecorators(container); 
 
    @Component({}) 
    export default class DriverSFC extends Vue { 
 
        @lazyInject(TYPES.DRIVER) 
        private _driver!: Driver; 
 
        // Lifecycle hook 
        public created() { 
            console.log('Retrieved driver: ', this._driver); 
            console.log('Driver initialized'); 
        } 
 
        public get driver(): string { 
            return this._driver.description; 
        } 
    } 
</script> 
 
<style scoped> 
 
</style> 

As you can see, the following are the only things that we need to do now:

Of course, this remains a post-construction injection and, hence, the definite assignment assertions remain necessary, but at least our component doesn't need to interact directly with the IoC container anymore.

This is a very useful improvement over our previous code and it brings us one step closer to a clean dependency injection design.

You can reuse this approach with React, which also instantiates components and prevents controller injection.

Now, let's talk about the user interface component libraries for Vue.