JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
<v-counter v-model="B" name="B" :min="0" :max="5"></v-counter>
<v-counter v-model="Q" name="Q" :min="0" :max="3"></v-counter>
<component
v-if="component"
:is="component.name"
v-bind="component.props"
></component>
</div>
CSS
* {
font-family: monospace;
}
JavaScript
Vue.component('c1', {
template: `<div :style="{ color }">component 1</div>`,
props: [ 'color' ],
});
Vue.component('c2', {
template: `<div :style="{ fontSize }">component 2</div>`,
props: [ 'fontSize' ],
});
Vue.component('c3', {
template: `<div :style="{ letterSpacing, border }">component 3</div>`,
props: [ 'letterSpacing', 'border' ],
});
Vue.component('c4', {
template: `<div :style="{ backgroundColor, padding }">component 4</div>`,
props: [ 'backgroundColor', 'padding' ],
});
Vue.component('v-counter', {
template: `
<div>
{{ name }}:
<button @click="$emit('input', value - 1)" :disabled="value <= min">-</button>
{{ value }}
<button @click="$emit('input', value + 1)" :disabled="value >= max">+</button>
</div>`,
props: [ 'value', 'name', 'min', 'max' ],
});
new Vue({
el: '#app',
data: {
components: [
{ name: 'c1', props: { color: 'red' } },
{ name: 'c2', props: { fontSize: '32px' } },
{ name: 'c3', props: { letterSpacing: '15px', border: '2px solid lime' } },
{ name: 'c4', props: { backgroundColor: 'yellow', padding: '20px' } }
],
Q: 2,
B: 1,
},
computed: {
component() {
return [ 1, 2 ].includes(this.Q) && this.components[this.B - 1];
},
},
});