Skip to content

Instantly share code, notes, and snippets.

@createvibe
Last active June 30, 2020 22:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save createvibe/310e32c5c98fb810b9c3798d49cb860b to your computer and use it in GitHub Desktop.
Save createvibe/310e32c5c98fb810b9c3798d49cb860b to your computer and use it in GitHub Desktop.
Vue dependency injection
{
"parameters": {
"service.cdn.constructor": "services/DevCdnService.js",
},
"services": [
]
}
{
"parameters": {
"service.security.constructor": "services/Security.js",
"service.cache.constructor": "services/CacheService.js",
"service.cdn.constructor": "services/CdnService.js",
"service.social.facebook.constructor": "services/Facebook.js"
},
"services": [
{
"id": "security",
"constructor": "%service.security.constructor%"
},
{
"id": "cache",
"constructor": "%service.cache.constructor%"
},
{
"id": "cdn",
"constructor": "%service.cdn.constructor%"
},
{
"id": "social.facebook",
"constructor": "%service.social.facebook.constructor%",
"arguments": ["%env.VUE_APP_FACEBOOK_ID%", "%env.VUE_APP_FACEBOOK_VERSION%"],
"calls": [
{
"method": "setOwnerAccountId",
"arguments": ["%env.VUE_APP_FACEBOOK_ACCOUNT_ID%"]
}
]
}
]
}
{
"parameters": {
},
"services": [
]
}
{
"parameters": {
"service.cdn.constructor": "services/DevCdnService.js",
},
"services": [
]
}
// conga libs
import di from '@conga/dependency-injection';
// set up the configuration from our .di.json files
// .di.json, .di.development.json, .di.production.json, .di.test.json
const env_config = require('./di.' + process.env.NODE_ENV + '.json');
const config = require('./di.json');
const merged_config = {
parameters: Object.assign(
config.parameters,
env_config.parameters,
Object.keys(process.env).reduce((env, key) => {
env['env.' + key] = process.env[key];
return env;
}, {})
),
services: config.services
};
for (const s2 of env_config.services) {
for (const [key, s1] of config.services) {
if (s1.id === s2.id) {
merged_config.services[key] = s2;
break;
}
}
}
/**
* The service container
* @type {{}}
*/
let container;
/**
* DependencyInjection allows us to control services per environment per component
*/
class DependencyInjection {
static get container() {
return container;
}
}
/**
* Install the DI plugin for VueJS
* @param Vue
* @param options
*/
DependencyInjection.install = function (Vue, options = {}) {
/* set up the container */
// create a service loader
const loader = new di.ServiceLoader([]);
// overload how the serviceloader loads so webpack can bundle properly
loader.load = path => {
try {
return require('@/' + path).default;
} catch(error){
throw new Error('Could not load: ' + path + '.');
}
}
// create a container builder with the loader
const builder = new di.ContainerBuilder(loader);
// build the container and retrieve it in a callback
builder.build(merged_config, serviceContainer => {
container = serviceContainer;
// assign the service container to the Vue instance `Vue`
Object.defineProperty(Vue, 'serviceContainer', {
value: container,
writable: false
})
// assign the container to Vue
Object.defineProperty(Vue.prototype, '$container', {
get() {
return Vue.serviceContainer;
}
});
if (options.parseBindParams === undefined || !!options.parseBindParams) {
Vue.mixin({
beforeCreate: function () {
// replace %service.name% with the service in <component serviceName="%service.name%" />
for (const key in this.$options.propsData || {}) {
const data = this.$options.propsData[key];
if (typeof data === 'string' && /^%[^%]*%$/.test(data)) {
const service = container.get(data.replace(/^%|%$/g, ''));
if (service) {
this.$options.propsData[key] = service;
}
}
}
}
});
}
});
}
export default DependencyInjection;
// import Vue
import Vue from 'vue';
// import the DI lib
import DI from './dependencyInjection'; // I have my code saved here
// initialize the dependency injection
Vue.use(DI, {
/* parseBindParam tells the DI lib to check for injection through parameters or not
ex: <component myService="%my.service%" />
%my.service% would be resolved to the service as a bound parameter */
parseBindParams: false
});
// Vue.serviceContainer.get('some.service').doSomething();
// DI.container.get('some.service').doSomething();
<template>
<section>
<div v-if="reactivity.something">
<p>{{ reactivity.somethingElse }} </p>
</div>
</section>
</template>
<script>
export default {
name: 'component',
data() {
return {
reactivity: this.$container.get('reactivity.works')
};
}
methods: {
doSomething() {
this.$container.get('some.service').doSomething();
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment