I have a thightly coupled duo of parent-child components using a scoped slot. In the parent, some data is received from the child via the scoped slot prop (let's call it myScopedProp). All is well with all of this. In the parent's scoped slot, I can pass myScopedProp as an argument to some methods in the parent script, that works.
Now how can I access this myScopedProp in a computed function present in the parent whithout first setting it as data? Is there a built in vuejs way to access myScopedProp from the parent script?
<!-- parent -->
<template>
<child>
<template #theSlot="{ myScopedProp}">
{{ parentMethod(myScopedProp) }} <-- this works fine
</template>
</child>
</template>
<!-- child -->
<template>
<slot name="theSlot" :myScopedProp="someChildValue">
</slot>
</template>
I presently hack this by passing to the child a method from the parent which sets the myScopedProp value in the parent's data, but that feels wrong and redundant since I already have this value passed via the scoped slot.
There's many options how to do this, I would use provide/inject
since the components are tightly bound. It's called lifting state. Even v-model
would work.
Another options:
defineExpose()
macro and a component ref:<script setup>
import { ref, provide, cloneVNode } from 'vue';
import Comp from './Comp.vue';
const slotProp = ref();
const $comp = ref();
const providedProp = ref();
provide('providedProp', providedProp);
</script>
<template>
<h1>{{ slotProp }}</h1>
<h1>{{ $comp?.prop }}</h1>
<h1>{{ providedProp }}</h1>
<comp ref="$comp" #="{prop}" v-assign="comp => directiveProp = comp.internal">{{ (slotProp = prop, '') }}</comp>
</template>
Comp.vue:
<script setup>
import {ref, inject} from 'vue';
const prop = ref('Slot prop');
const exposed = ref('Exposed prop');
defineExpose({prop: exposed});
const provided = inject('providedProp');
provided.value = 'Provided prop';
const changeProps = () => {
[prop, exposed, provided].forEach(r => r.value += ' changed')
};
</script>
<template>
<div>
<slot v-bind="{prop}"/>
<div>
<button @click="changeProps">Change props</button>
</div>
</div>
</template>