【vue3】 使用JSX实现普通、具名和作用域插槽

最近在vue3构建的项目中使用到了JSX(不得不说JSX用起来的感觉就是清爽)。但是前段时间遇到了一个问题,vue template中的slot插槽如何在JSX中实现呢?查了很久资料、文档都很难找到一个能够直接解决我的问题的方案,后来各个文档中找到的线索拼接起来后逐渐尝试才实现。

一、普通插槽和具名插槽

vue中最简单的插槽写法,这里我们都统一写出父组件、子组件的插槽引用方式。

vue中的写法:

子组件

<template>
    <div>
        <span>I'm Child</span>
        <slot></slot>
        <slot name="header"></slot>
    </div>
</template>

<script>
export default {
    name: "Test"
}
</script>

<style>
</style>

父组件

<template>
    <TestComponent>
        <template #default>
            <span>这是默认插槽</span>
        </template>
        <template #header>
            <span>这是header插槽</span>
        </template>
    </TestComponent>
</template>

<script>
import TestComponent from './TestComponent'
export default {
    name: "Parent",
    components: {
        TestComponent
    }
}
</script>

<style>

</style>

现在我们来看看JSX的写法:

子组件

import { defineComponent } from "@vue/runtime-core";

export default defineComponent({
    name: "Test",
    render() {
        return (
            <>
                <span>I'm Child</span>
                { this.$slots.default?.() }
                { this.$slots.header?.() }
            </>
        )
    }
})

父组件

import { defineComponent } from 'vue'
import TestComponent from './TestComponent'

export default defineComponent({
    name: "Test",
    components: {
        TestComponent
    },
    render() {
        return (
            <TestComponent v-slots={{
                default: () => (
                    <>这是默认插槽</>
                ),
                header: () => (
                    <>这是header插槽</>
                )
            }}>
            </TestComponent>
        )
    }
})

可以看到,父组件通过 v-slots 属性去定义插槽,子组件直接在 render 中通过 this.$slots[name] 去获取。

二、作用域插槽

其实作用域插槽在JSX中的写法也一样,只需要将scope作为参数传递即可。

vue中的写法

子组件:

<template>
    <div>
        <span>I'm Child</span>
        <slot name="content" :value="value"></slot>
    </div>
</template>

<script>
export default {
    name: "Test",
    setup() {
        return {
            value: {
                name: 'xzw'
            }
        }
    }
}
</script>

<style>

</style>

父组件:

<template>
    <TestComponent>
        <template #content="scope">
            {{ scope.value.name }}
        </template>
    </TestComponent>
</template>

<script>
import TestComponent from './TestComponent.vue'
export default {
    name: "Parent",
    components: {
        TestComponent
    }
}
</script>

<style>

</style>

JSX中的写法:

子组件

import { defineComponent } from "@vue/runtime-core";

export default defineComponent({
    name: "Test",
    setup() {
        return {
            value: {
                name: 'xzw'
            }
        }
    },
    render() {
        return (
            <>
                <span>I'm Child</span>
                { this.$slots.content?.(this.value) }
            </>
        )
    }
})

父组件

import { defineComponent } from 'vue'
import TestComponent from './TestComponent'

export default defineComponent({
    name: "Test",
    components: {
        TestComponent
    },
    render() {
        return (
            <TestComponent v-slots={{
                content: scope => (
                    <>{scope.name}</>
                )
            }}>
            </TestComponent>
        )
    }
})

你可能感兴趣的:(vue3知识收集,vue)