Я определил свойства в родительском компоненте, которые затем передаются извне родительскому компоненту. Как я могу использовать эти свойства в дочернем компоненте.
Родитель.vue
<script setup>
defineProps({
col: { type: Number, default: 3 },
// default | auto | mid | large | large2x
labelWidth: { type: String, default: 'default' },
})
</script>
<template>
<div>
<slot></slot>
</div>
</template>
Child.vue
<script setup>
</script>
<template>
<!-- How to use labelWidth from parent component here -->
<div>
<label>Hello</label>
<slot></slot>
</div>
</template>
App.vue
<script setup>
import Parent from 'Parent.vue'
import Child from 'Child.vue'
</script>
<template>
<Parent label-width = "large">
<Child></Child>
<Child></Child>
</Parent>
</template>
Я бы сделал это так:
Родитель.vue
<script setup>
defineProps({
col: { type: Number, default: 3 },
// default | auto | mid | large | large2x
labelWidth: { type: String, default: 'default' },
});
</script>
<template>
<div>
<slot :labelWidth = "labelWidth"></slot>
</div>
</template>
Child.vue
<script setup>
defineProps({
label: { type: String, default: "child-default" },
});
</script>
<template>
<label>{{ label }}</label>
<hr/>
<div>
<label>Hello</label>
<slot></slot>
</div>
</template>
App.vue
<script setup>
import Parent from 'Parent.vue'
import Child from 'Child.vue'
</script>
<template>
<Parent label-width = "large" v-slot = "{ labelWidth }">
<Child :label = "labelWidth"/>
<Child />
</Parent>
</template>
Надеюсь, это будет полезно.
ПС: Этот небольшой курс можно использовать бесплатно. https://vueschool.io/courses/reusable-vuejs-comComponents-with-slots
Вы можете использовать функцию рендеринга, чтобы добавить дополнительные реквизиты в слот Родителя по умолчанию (я передал все реквизиты Родителя, вы можете настроить их).
Вы можете проверить, какие реквизиты поддерживаются дочерними компонентами, и передавать их только через реквизиты, чтобы избежать резервных атрибутов.
Родитель.vue
<script setup>
import {useSlots, h} from 'vue';
const props = defineProps({
col: { type: Number, default: 3 },
// default | auto | mid | large | large2x
labelWidth: { type: String, default: 'default' },
})
const $slots = useSlots();
const slotted = () => $slots.default().map(vnode => {
const filtered = (vnode.type.props ?? []).reduce((r, key) => (r[key] = props[key], r), {});
return h(vnode, filtered);
});
</script>
<template>
<div>
<slotted/>
</div>
</template>
Child.vue
<script setup>
defineProps(['labelWidth']);
</script>
<template>
<!-- How to use labelWidth from parent component here -->
<div>
<label>Hello (labelWidth: {{labelWidth}})</label>
<slot></slot>
</div>
</template>
Если ваш дочерний элемент всегда используется вместе с родительским и/или все родительские компоненты всегда предоставляют labelWidth
, вы можете использовать предоставление/внедрение:
Родитель.vue
<script setup>
import { provide } from 'vue';
const props = defineProps({
col: { type: Number, default: 3 },
// default | auto | mid | large | large2x
labelWidth: { type: String, default: 'default' },
})
provide('labelWidth', props.labelWidth);
</script>
<template>
<div>
<slot/>
</div>
</template>
Child.vue
<script setup>
import {inject} from 'vue';
const labelWidth = inject('labelWidth');
</script>
<template>
<!-- How to use labelWidth from parent component here -->
<div>
<label>Hello (labelWidth: {{labelWidth}})</label>
<slot></slot>
</div>
</template>
Если вам не нравится менять Родителя, вы можете посмотреть его реквизиты в Дочернем элементе:
Child.vue
<script setup>
import {getCurrentInstance, ref, watch} from 'vue';
const self = getCurrentInstance();
const labelWidth = ref();
watch(() => self.parent.props?.labelWidth, value => labelWidth.value = value, {immediate: true});
</script>
<template>
<!-- How to use labelWidth from parent component here -->
<div>
<label>Hello (labelWidth: {{labelWidth}})</label>
<slot></slot>
</div>
</template>