Skip to content

无渲染组件

在 Vue(包括 Vue 2 / Vue 3)中,无渲染组件(Renderless Component) 指的是:

👉 不关心具体 UI 渲染,而只负责提供逻辑和状态的组件。 也就是说,它本身不会输出 DOM 结构,而是通过 插槽(slot,特别是作用域插槽)setup 返回数据,把逻辑暴露给外部组件去决定如何渲染。


🎯 为什么需要无渲染组件?

  1. 逻辑复用:可以把通用逻辑(比如表单验证、鼠标拖拽、数据请求)抽离出来。
  2. UI 灵活:渲染交给调用者,避免组件内部强绑定样式或结构。
  3. 更高的可组合性:搭配 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

Released under the MIT License.