I have two unrelated context components which share logic and template in a way that looks like one is extending the other.
Imagine Drop and Pick components like this:
// pick.js
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class Pick extends Vue {
template: '<p>{{name}}</p>',
created() {
console.log('Hello Pick');
}
data: {
name: 'pick',
count: 0
},
methods: {
add: function () {
this.count ;
}
}
}
// drop.js
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class Drop extends Vue {
template: '<p>{{name}}</p> <span v-if="isUserFriendly">Greetings!!!</span>',
created() {
console.log('Hello Drop');
}
data: {
name: 'drop',
isUserFriendly: false,
count: 0,
drops: 0
},
methods: {
add: function () {
this.count ;
this.drops ;
},
remove: function () {
this.count--;
},
}
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Intuitively, one can say Drop is extending Pick while adding some functionality and alter the template. This seems to be a good solution but then I thought to myself that to achieve that Pick template should look like this:
<p>{{name}}</p>
<span v-if="isUserFriendly">Greetings!!!</span>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Remember that I said unrelated context components? Now Pick needs to know about isUserFriendly which is unacceptable nor I think its the right solution. Moreover it will create overhead in the future as inheritance can be hard to maintain (imagine more components to extend and logic to share).
What do you think will be the best approach here? Maybe there is another way around which Im not familiar with?
Thanks for the help!
CodePudding user response:
Component composition is a common way to do this. Drop component contains a superset of functionality, i.e. pick component should allow to be wrapped in a way that will allow for desired output and behaviour.
For parent-child relationship, data pieces are passed as props and events, and view pieces are passed as slots.
Additional logic stays in parent component.
In child component (Pick
):
<div>
<p>{{name}}</p>
<slot name="extraText"/>
</div>
and
add: function () {
this.count ;
this.$emit('add');
}
In parent component (Drop
):
<Pick @add="drops ">
<template v-slot:extraText>
<span>Greetings!!!</span>
</template>
</Pick>