All Projects → dealloc → Vuec

dealloc / Vuec

A simple IoC container for VueJS 2

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Vuec

Caddy V1 Service
⬛️ Run Caddy as a service
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
Sqlinator
Automatically forward HTTP GET & POST requests to SQLMap's API to test for SQLi and XSS
Stars: ✭ 70 (-2.78%)
Mutual labels:  plugin
Hovercard
🖱️ Wikipedia summary cards for the web
Stars: ✭ 72 (+0%)
Mutual labels:  plugin
Smqtk
Python toolkit for pluggable algorithms and data structures for multimedia-based machine learning.
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
My Custom Functionality
A basic starter plugin to load assets like CSS and JS files in WordPress.
Stars: ✭ 70 (-2.78%)
Mutual labels:  plugin
Gruvbox Intellij Theme
An IDE theme based on the gruvbox color scheme. ⛺
Stars: ✭ 71 (-1.39%)
Mutual labels:  plugin
Googleclientplugin
Google Client Plugin for Xamarin iOS and Android
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
Blockpets
An advanced pets plugin for PocketMine-MP
Stars: ✭ 72 (+0%)
Mutual labels:  plugin
Mautic Contact Client
Create custom integrations without writing code, like having your own Zapier.
Stars: ✭ 70 (-2.78%)
Mutual labels:  plugin
Kirki
Extending the customizer
Stars: ✭ 1,175 (+1531.94%)
Mutual labels:  plugin
Wp Missed Schedule
Find only missed schedule posts, every 15 minutes, and republish correctly 10 items each session. The Original plugin (only this) no longer available on WordPress.org for explicit author request! Compatible with WP 2.1+ to 4.9+ and 5.0-beta3 (100.000+ installs 300.000+ downloads 2016-04-13) Please: do not install unauthorized malware cloned forked!
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
Streamdeck Homeassistant
🏠 Use the Elgato Stream Deck as Home Assistant controller. Call any available service and toggle lights or resume your music.
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
Xcodeappplugintemplate
App Plugin Project Template For iOS App And Mac App. Make it easy to hook app.
Stars: ✭ 71 (-1.39%)
Mutual labels:  plugin
Burpsuite Changeu
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
Jmeter Elasticsearch Backend Listener
JMeter plugin that lets you send sample results to an ElasticSearch engine to enable live monitoring of load tests.
Stars: ✭ 72 (+0%)
Mutual labels:  plugin
Wordpress Plugin Installer
A PHP class for installing and activating WordPress plugins.
Stars: ✭ 69 (-4.17%)
Mutual labels:  plugin
Vagrant Foodshow
Vagrant plugin for ngrok
Stars: ✭ 70 (-2.78%)
Mutual labels:  plugin
Serverless Plugin Webpack
Serverless Plugin Webpack
Stars: ✭ 72 (+0%)
Mutual labels:  plugin
Foal
Elegant and all-inclusive Node.Js web framework based on TypeScript. 🚀.
Stars: ✭ 1,176 (+1533.33%)
Mutual labels:  dependency-injection
Bottlejs
A powerful dependency injection micro container for JavaScript applications
Stars: ✭ 1,171 (+1526.39%)
Mutual labels:  dependency-injection

Vuec

Vue container - a simple IoC container for Vue 2

UNMAINTAINED WARNING I don't use Vuec myself anymore, and I hardly have time to maintain Vuec. If you are interested in taking over the project feel free to contact me.

Installation

Install using yarn add vue-container or npm install --save vue-container

warning: when building for production, make sure to read this

Dependencies

NONE! We don't even depend on VueJS (except in the devDependencies for unit testing). You can even use this without Webpack or Browserify, the container is accessible from window.vuec.Container and the Vue bindings as vuec.default (the unit tests are actually written in plain ES5 so you can start there to get an idea!)

Introduction

If you have worked with Vue before, you'll probably have done things like this:

<script>
import Axios from 'axios';

export default {
	name: 'SomeComponent',
	data: () => ({
		message: null,
	}),
	created() {
		Axios.get('/your/api').then((response) => {
			this.message = response.data;
		});
	},
};
</script>

You can use plugins to inject dependencies into your Vue object, but that also means that every dependency you need somewhere would have to be injected on every instance of Vue you make.

With vuec you can write the same code as above like this:

<script>
export default {
	name: 'SomeComponent',
	data: () => ({
		message: null,
	}),
	created(Axios) {
		Axios.get('/your/api').then((response) => {
			this.message = response.data;
		});
	},
};
</script>

Note how we're no longer importing the Axios module. Vuec takes care of injecting your dependencies into your hooks. Except for beforeCreate all hooks can specify their dependencies and Vuec will inject them.

Why use dependency injection?

In the example above we showed you how you could eliminate your imports (mostly) by using dependency injection. You might by now be thinking "hey that's pretty cool, but why would I do that?". There's a couple reasons why you might want to use dependency injection in VueJS

  • testability (we'll cover this one in detail below)
  • explicit dependencies: rather than having a bunch of imports thrown all over, you can now see what dependencies your component relies on (because other than dependencies you might import components, css files, ...)
  • easier refactoring (rather than having to wrap those modules so you can swap them, just swap their binding in the container)

As mentioned above in the list, testability is improved by using dependency injection. Imagine you're writing an application that makes calls to an API, you're probably using a package for making those HTTP requests (like vue-resource or Axios or even fetch). However, when you're running your unit tests you'd probably rather not have those tests run wild and create 200 users in your API. Using dependency injection you could just swap out the binding for your HTTP service with a dummy service (that could for example assert the required calls are made), without having to change a single line of code.

Simply put, in your code you could have:

import Axios from 'axios';

Vue.$ioc.register('$http', Axios);

function convertCurrency() {}

Vue.$ioc.register(convertCurrency); // will be registered as 'convertCurrency'

class PostService {}

Vue.$ioc.register(new PostService()); // will be registered as 'PostService'

And for your unit tests you could overwrite the binding

Vue.$ioc.register('$http', AxiosDummyModule);
Vue.$ioc.register('convertCurrency', DummyFunc);
Vue.$ioc.register('PostService', DummyService);

Your components however remain entirely unchanged.

in short depenency injection allows you to abstract your code a step further and makes your components truly standalone and easier to test.

Usage

registering Vuec in your application is as easy as

import Vuec from 'vue-container';

Vue.use(Vuec);

Registering a dependency in the container (like Axios in the above example) is done using register

Vue.$ioc.register('Axios', Axios);
// Or inside a Vue component:
this.$ioc.register('Axios', Axios);

Also you can pass dependencies map to container when register plugin

import Vuec from 'vue-container';

Vue.use(Vuec, {
  register: {
    $http: Axios
  }
});

You can also manually resolve from the container using the resolve function:

Vue.$ioc.resolve('Axios');
// Or inside a Vue component:
this.$ioc.resolve('Axios');

so what happens when you try to resolve a dependency that does not exist? That depends, in development this will throw an error, but in production it will silently return undefined. You can test for production mode on the production property of the container. You can enable production mode by setting the environment variable NODE_ENV=production

this.$ioc.resolve('foo');
// in development this would throw Unknown dependency "foo"
// in production this returns undefined

So how do you call a function with all it's dependencies?

function test(Axios) {
	console.info(Axios);
}

Vue.$ioc.prepare(test)();
// Or inside a Vue component:
this.$ioc.prepare(test)();

But you didn't pass Axios as an argument!

Indeed, the prepare method of Vuec returns a bound copy of the function with all it's parameters already bound, you can call this function as many times as you want and it will have it's dependencies every time. If you want a custom scope, you can always pass your this argument as the second parameter to the prepare method.

function test(Axios) {
	console.info(Axios);
}

const prepared = Vue.$ioc.prepare(test);
prepared();
prepared();
prepared();

In the above example despite being called 3x the container will only have to resolve the dependencies once!

Usage with VueJS

Vuec will automatically hook itself into the component lifecycle to resolve dependencies, or if you prefer you can use the services property to define your dependencies, it's up to your preference.

To use method injection, you simply write your components like this:

new Vue({
    // ... pass your component parameters here
    mounted($http) {
        // vuec will inject the '$http' service for you here
    }
});

Or if you prefer to define your services in an array on your component (which prevents name mangling)

new Vue({
    // ... pass your component parameters here
    services: ['$http'],
    mounted() {
        // the $http service is available under this.$services.$http
    }
});

Does this work with Vue 1.x?

It probably should, given that Vue manages it's hooks the same way, but it hasn't been tested yet, if you do feel free to make an issue and report any problems you run into.

mangling

When building for production you'll most likely minify your code. Most minifiers employ a technique called "name mangling" which poses a couple problems with this library if you use method injection. You can read more about this here.

In short, you'll need to ensure your minifier won't mangle the parameter names of your services, for UglifyJS (default for webpack) this can be done like this:

new webpack.optimize.UglifyJsPlugin({
  compress: {
    warnings: false
  },
  sourceMap: true,
  mangle: {
    except: ['Service'], // blacklist your services from being mangled
  }
})

What's new?

  • 21/04/2017
    • added unregister to remove bindings and bindings to get all registered services.
    • added has method to check if a container has a binding
  • 28/04/2017
    • added instance binding
    • updated documentation with warning about name mangling
  • 29/04/2017
    • added production and development mode
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].