Dependency Injection
in Vue.js
Who Am I?
- Alex Riviere
- Design Engineer for NexTraq
- Co-Organizer for Atlanta Vue.js Meetup
WARNING
Advanced Vue.js Concepts Ahead
May Cause:
- Confusion
- Sense of Wonder
- Smug satisfaction of knowing more than others.
Methods of Passing State Between Components
- Props/Emit
- External Store (Vuex)
- $root/$parent (Not Advised)
- Provide/Inject
Props Down, Events Up
<parent-component>
<child-component>
<grand-child-component />
$props
$props
$emit
$emit
</child-component>
</parent-component>
Props Down, Events Up
- Explicitly Defined Props and Events
- Creates reusable components
- Doesn't rely on outside data structures
- Easily testable
Global Store
<fox-component />
<whale-component />
<unicorn-component />
Vuex $store
state
state
state
mutation
mutation
mutation
Global Store
- Useful for large applications with shared state
- Can be used along with props/$emit
- Implicitly uses $store
- Relies on external dependency
- Not ideal for publishing modules
I am $root
<walking-tree-component>
<raccoon-component>
<laser-pew-pew-component />
$root.bitOfData
</raccoon-component>
</walking-tree-component>
I am $root?
<walking-tree-component>
<raccoon-component>
<laser-pew-pew-component />
$root.bitOfData?
</raccoon-component>
</walking-tree-component>
<galaxy-guardians>
</galaxy-guardians>
$parent Knows Best
<parent-component>
<child-component>
<grand-child-component />
$parent.knowledge
$parent.$parent.knowledge
(Has a bit of data called knowledge)
</child-component>
</parent-component>
$parent Knows Best ?
<parent-component>
<grand-child-component />
$parent.$parent.knowledge?
</parent-component>
Dependency Injection
<parent-component>
<grand-child-component />
provide
inject
<child-component>
<grand-parent-component>
</child-component>
</parent-component>
</grand-parent-component>
Dependency Injection
<providing-component>
<injecting-component />
<child-component>
<child-component>
<root-component>
_provided.bit_of_data
inject:['bit_of_data']
_provided.bit_of_data?
_provided.bit_of_data?
this.bit_of_data
</child-component>
</child-component>
</providing-component>
</root-component>
SHOW ME
HOW ALREADY!
<div>
<p>
This is the count:
</p>
<p>{{count}}</p>
<slot />
<button
@click="count++"
class="button">
Increment!
</button>
</div>
SimpleProvide.vue
export default {
name: 'simple-provide',
data(){
return {
count: 1,
};
},
provide(){
return {
'count': this.count
};
},
}
Template
Script
<div>
<p>
This is the
injected count:
</p>
<p>
{{count}}
</p>
</div>
SimpleInject.vue
export default {
name: "simple-inject",
inject: ['count'],
}
Template
Script
Simple Demo
How do we make this Reactive?
RxJS!
NO!!
<div>
<p>
This is the
parent text:
</p>
<p>{{text}}</p>
<input
type="text"
v-model="text" />
<slot />
</div>
ReactiveProvide.vue
export default {
data() {
return {
text: "Hello World",
}
},
provide() {
return {
getText: ()=>this.text,
setText: v=>this.text=v,
}
},
}
Template
Script
<div>
<p>
Injected text:
</p>
<p>{{ text }}</p>
<input
type="text"
v-model="text" />
</div>
ReactiveInject.vue
export default {
name:"reactive-inject",
inject: [
"getText",
"setText",
],
computed: {
text: {
get() {
return this.getText()
},
set(d) {
this.setText(d)
},
}
},
}
Template
Script
Reactive Demo
ReactiveProvide.vue
import {ref, provide} from 'vue';
export default {
setup(){
const text = ref('Hello World');
provide('text', text);
return {text}
},
}
Vue 2 + 3
Vue 3 Composition API
export default {
data() {
return {
text: "Hello World",
}
},
provide() {
return {
getText: ()=>this.text,
setText: v=>this.text=v,
}
},
}
ReactiveInject.vue
import {inject} from 'vue'
export default {
name:"reactive-inject",
setup(){
const text = inject('text');
return {text};
},
}
Vue 2 + 3
Vue 3 Composition API
export default {
name:"reactive-inject",
inject: [
"getText",
"setText",
],
computed: {
text: {
get() {
return this.getText()
},
set(d) {
this.setText(d)
},
}
},
}
Helpful Packages
vue-reactive-provide
Plugin/Mixin wrapping Vue's static 'provide/inject' feature allowing to easily pass reactive data to children
(I had to put the V somewhere.)
Where should I use this?
When data is implicitly expected to be available. A good example is compound components where the children components only function inside of their parent components.
Let's look at an example using an accordion and splitting it up into multiple components.
Demos!
This example was blatantly stolen from Cassidy Williams' React Hooks Workshop
Follow Cassidy, because she is awesome:
twitter: cassidoo
Questions?
Dependency Injection in Vue.js - Vuejs.Berlin 2020
By Alex Riviere
Dependency Injection in Vue.js - Vuejs.Berlin 2020
- 696