On gists
Ref slot (Options vs Composition, Parent / Child, Child / Parent)
•
Popular ⭐
Vue.js
ChildToParent-ScopedSlot.vue
Raw
#
<!-- 1) From Child to Parent via scoped slot and dynamic ref-->
<!-- App.vue-->
<template>
<div id="app">
<HelloWorld v-slot="{ setRef }">
<input type="text" :ref="(el) => setRef(el)" />
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
name: 'App',
components: {
HelloWorld,
},
};
</script>
<!-- Hello world -->
<template>
<slot v-bind="{ setRef }"></slot>
<button @click="setFocus">SET</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
ref: ''
}
},
methods: {
setFocus()
{
this.ref.focus()
},
setRef(el) {
this.ref = el
console.log(el)
}
}
}
</script>
ParentToChild.vue
Raw
#
<!-- 2) From parent to child via method that set ref -->
<!-- App.vue -->
<template>
<div id="app">
<HelloWorld name="child" :b="setRefOnA">
<input type="text" ref="a" value="default value of this input" />
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
name: 'App',
components: {
HelloWorld,
},
methods: {
setRefOnA(el) {
return this.$refs.a;
},
},
};
</script>
<!-- HelloWorld.vue -->
<template>
<div>
<slot> ... </slot>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: ['b'],
mounted() {
console.log(this.b().focus());
},
};
</script>
Composition-Child-to-Parent.vue
Raw
#
<!-- Same as 1 but in Composition API -->
<!-- App.vue -->
<script setup>
import SlotVue from "./Slot.vue"
</script>
<template>
<SlotVue>
<template #child="{ setRef }">
<button :ref="(el) => setRef(el)">
child
</button>
</template>
</SlotVue>
</template>
<!-- Slot.vue - child -->
<script setup>
import { ref } from 'vue'
const slotRef = ref()
const setSlotRef = (el) => {
console.log(el, "xxcc") // only once in assign
slotRef.value = el;
}
const onClick = () => {
console.log(slotRef.value)
}
</script>
<template>
<p>
press f12 to open a developer tools
</p>
<slot name="child" :set-ref="setSlotRef"/>
<button @click="onClick">
console.log slot
</button>
</template>
ParentToChild-computed-methods.j
Raw
#
<template>
{{ computedRef }}
<hr />
<div v-if="myProp">
{{ computedRefButton }}
</div>
<hr />
<Foo :heading="refHeading" :textarea="refTextarea" :section="computedRef">
<section ref="computedRef">
<h2 ref="heading">Heading</h2>
<textarea ref="textarea"></textarea>
<br />
<button ref="button">test</button>
</section>
</Foo>
</template>
<script>
import Foo from './components/Foo.vue';
export default {
name: 'App',
components: {
Foo,
},
data() {
return {
isMounted: false,
myProp: true,
};
},
computed: {
computedRef() {
if (!this.isMounted) return;
console.log(this.$refs.computedRef);
return this.$refs.computedRef;
},
computedRefButton() {
return this.$refs.button;
},
},
methods: {
refHeading() {
return this.$refs.heading;
},
refTextarea() {
return this.$refs.textarea;
},
},
mounted() {
this.isMounted = true;
},
updated() {
console.log(this.$refs);
},
};
</script>
// Child.vue
<template>
<div>
<slot> ... </slot>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: ['b'],
mounted() {
console.log(this.b().focus());
},
};
</script>
CompositionApi.vue
Raw
#
// PARENT -> CHILD
// PARENT
<!-- App.vue-->
<template>
<HelloWorld v-slot="{ setRef }">
<input type="text" :ref="(el) => setRef(el)" />
</HelloWorld>
</template>
<script setup>
import HelloWorld from './HelloWorld.vue';
</script>
// CHILD
<template>
<slot v-bind="{ setRef }"></slot>
<button @click="setFocus">SET</button>
</template>
<script setup>
import { ref } from 'vue';
const myInputFromSlot = ref(null); // what ever name
const setFocus = () => {
myInputFromSlot.value.focus();
};
const setRef = (el) => {
myInputFromSlot.value = el
console.log(el);
};
</script>
// CHILD -> PARENT
// PARENT
<!-- App.vue-->
<template>
<HelloWorld :ref-to-child="setRefToChild">
<input type="text" ref="inputak" />
</HelloWorld>
</template>
<script setup>
import { ref } from "vue"
import HelloWorld from './HelloWorld.vue';
const inputak = ref()
const setRefToChild = () => inputak
</script>
// CHILD
<template>
<slot></slot>
</template>
<script setup>
import { onMounted } from 'vue'
const props = defineProps(['refToChild'])
onMounted(() => {
console.log(props.refToChild().value.focus())
})
</script>
ParentToChildWithFullReactivity.
Raw
#
<!-- UMI REAKTIVITU, musi byt predany objekt! -->
<!-- Parent Usage -->
<recipe-row-marker v-slot="{ toggle }">
<input
v-model="toggle.isDone"
type="checkbox"
class="form-control"
/>
</recipe-row-marker>
<!-- RecipeRowMarker.vue -->
<template>
<slot v-bind="{ toggle }" />
</template>
<script setup>
import { ref } from 'vue'
const toggle = ref({
isDone: false
})
</script>
<style scoped>
:slotted(.IsDone :where(.RecipeStep__Heading, .RecipeStep__Text)) {
@apply opacity-50 line-through;
}
</style>