无渲染组件
在 Vue(包括 Vue 2 / Vue 3)中,无渲染组件(Renderless Component) 指的是:
👉 不关心具体 UI 渲染,而只负责提供逻辑和状态的组件。 也就是说,它本身不会输出 DOM 结构,而是通过 插槽(slot,特别是作用域插槽) 或 setup 返回数据,把逻辑暴露给外部组件去决定如何渲染。
🎯 为什么需要无渲染组件?
- 逻辑复用:可以把通用逻辑(比如表单验证、鼠标拖拽、数据请求)抽离出来。
- UI 灵活:渲染交给调用者,避免组件内部强绑定样式或结构。
- 更高的可组合性:搭配 Vue 组合式 API / 插槽,可以更灵活地封装复杂逻辑。
📌 示例:计数器(无渲染)
vue
<!-- Counter.vue -->
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
const increment = () => count.value++
const decrement = () => count.value--
defineExpose({
count,
increment,
decrement,
})
</script>
<template>
<!-- 只暴露插槽,不渲染具体 UI -->
<slot :count="count" :increment="increment" :decrement="decrement"></slot>
</template>📌 使用方式
vue
<template>
<Counter v-slot="{ count, increment, decrement }">
<div>
<p>当前计数:{{ count }}</p>
<button @click="decrement">-</button>
<button @click="increment">+</button>
</div>
</Counter>
</template>
<script setup lang="ts">
import Counter from './Counter.vue'
</script>这里:
Counter组件不渲染任何固定的 UI- 外层完全自由决定 UI 的样子
📌 应用场景
- 表单验证逻辑封装(比如只提供验证状态,不渲染表单)
- 列表分页逻辑(只返回数据和分页状态,UI 由外部决定)
- 鼠标 / 键盘交互(拖拽、悬停检测等)
- 通用数据获取(
useFetch逻辑封装为 renderless 组件)
✅ 总结
无渲染组件 = 提供逻辑,不负责 UI。 在 Vue 中一般通过 作用域插槽 来实现,类似 React 中的 Render Props。
