18.5.5 ClientOnly 组件
模板里总有一部分内容不适合服务端渲染(依赖浏览器环境、或两端渲染结果必然不一致),
<ClientOnly>让这部分内容只在客户端渲染。
一、原理
<ClientOnly> 组件在服务端渲染时会被完全忽略,仅在客户端被渲染。实现依据是:
onMounted钩子只会在客户端执行。
所以只需用一个标记变量记录「是否已进入客户端」,再决定是否渲染默认插槽。
二、实现
import { ref, onMounted, defineComponent } from 'vue'
export const ClientOnly = defineComponent({
setup(_, { slots }) {
// 标记变量,仅在客户端渲染时为 true
const show = ref(false)
// onMounted 只会在客户端执行
onMounted(() => {
show.value = true
})
// 服务端什么都不渲染,客户端才渲染插槽内容
return () => (show.value && slots.default ? slots.default() : null)
}
})
使用:
<ClientOnly>
<SomeBrowserOnlyWidget />
</ClientOnly>
服务端首次渲染时
show为false,输出为空;客户端激活时onMounted触发,show变为true,插槽内容才被渲染 —— 这也要求插槽内容不参与激活比对,因此适合放图表、地图等纯客户端产物。
相关
- 18.5.2 使用跨平台的 API:另一种处理两端差异的思路——守卫平台 API
- 18.5.4 避免交叉请求引起的状态污染:客户端专属状态在服务端必须隔离