3👍
✅
Updating after a correcting comment from thanksd. I stumbled onto the right answer without really understanding it.
The problem is that within the slot, display
refers to an item in the scope-slot object. Updating it there does not update the actual source variable. If you pass in and call a function, the proper variable is updated.
Vue.component('dropdown', {
props: ['expanded'],
data: function() {
return {
display: Boolean(this.expanded)
}
},
methods: {
toggle() {
this.display = !this.display;
}
},
template: '<div><transition name="expand"><slot :display="display" :toggle="toggle"></slot></transition></div>'
});
new Vue({
el: '#app'
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<dropdown>
<div slot-scope="{display, toggle}">
<a href="javascript:void(0)" @click="toggle">Toggle {{ display }}</a>
<div v-if="display">
Dropdown content
</div>
</div>
</dropdown>
</div>
1👍
One solution would be to implement a v-model
for the dropdown
component which would allow you to two-way bind the display
property to a property in the parent. That way you wouldn’t need to pass anything via the slot-scope
.
Here’s an example of that:
Vue.component('dropdown', {
props: [ 'value' ],
data() {
return {
display: !!(this.value)
}
},
watch: {
value(value) {
this.$emit('input', value);
}
},
template: '<div><transition name="expand"><slot></slot></transition></div>'
});
new Vue({
el: '#app',
data() {
return { dropdownToggle: false }
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<dropdown v-model="dropdownToggle">
<div>
<a href="javascript:void(0)" @click="dropdownToggle = !dropdownToggle">
Toggle {{ dropdownToggle }}
</a>
<div v-if="dropdownToggle">
Dropdown content
</div>
</div>
</dropdown>
</div>
Source:stackexchange.com