You've probably learned that provide
and inject
allow you to do dependency injection.
In fact, the official docs tell you this specifically.
But that is completely wrong.
The provide
and inject
features have nothing to do with dependency injection, and I'll show you why.
But before we can get into that, we have to quickly cover what dependency injection is.
Dependency injection is a concept that comes from the Object Oriented Programming world.
Here is the definition:
A technique where one object supplies the dependencies of another object
The goal of dependency injection is to decouple these objects — to make it easier to change which objects are being used to get stuff done.
The dependencies aren't created by the object itself. Instead they are injected into the object when the program is running. These dependencies are the objects that supply the logic and behaviour of the program.
If you had a Javascript Trip
class that needed to get a route between two points, you could hard code the object it needs like this:
class Trip {constructor(pointA, pointB) {this.pointA = pointA;this.pointB = pointB;this.Router = new Router();}calculateRoute() {return this.Router.route(this.pointA, this.pointB);}}
Here the Router
class can never change. The Trip
class will always use the Router
class to calculate the route.
But if you wanted to be able to swap how the route was calculated, for example, between an algorithm for driving and an algorithm for walking, you can't do it like this. You need to use depenendency injection.
To do this, we'll refactor our class so that we pass in the Router
object instead:
class Trip {constructor(pointA, pointB, Router) {this.pointA = pointA;this.pointB = pointB;this.Router = Router;}calculateRoute() {return this.Router.route(this.pointA, this.pointB);}}
Now we can pass in whatever kind of Router
we want to use.
By using dependency injection like this, our Trip
class is no longer tied to a specific Router
class. We have the flexibility of changing it whenever and however we want.
That's why we use dependency injection.
There are several other benefits as well:
Now that we've covered what dependency injection is, we can move on to showing how it would be used in Vue.
In Vue, we're using components, not objects, so true dependency injection would look a little different.
Our definition here would be:
A technique where one component supplies the dependencies of another component
Again, these dependencies are the logic and behaviour of the program, not the data or state that's being processed.
Our main problem is that provide
/inject
cannot be used for dependency injection in this way for a few reasons:
provide
/inject
to pass data actually increases the coupling between components.provide
makes it available to the whole subtree.provide
/inject
is used is so that we can pass data deep into our component tree more easily. Dependency injection has nothing to do with the data of an application.Real dependency injection in Vue would either:
If provide
and inject
are not meant to be used for dependency injection, then what are they supposed to be used for?
I have lots of thoughts on this as well, but you'll have to wait for my post on that.