packages/src/app/components/client-only.mjs
export default defineComponent({ name: 'ClientOnly', // eslint-disable-next-line vue/require-prop-types props: ['fallback', 'placeholder', 'placeholderTag', 'fallbackTag'], setup (_, { slots }) { const mounted = ref(false) onMounted(() => { mounted.value = true }) return (props) => { if (mounted.value) { return slots.default?.() } const slot = slots.fallback || slots.placeholder if (slot) { return slot() } const fallbackStr = props.fallback || props.placeholder || '' const fallbackTag = props.fallbackTag || props.placeholderTag || 'span' return createElementBlock(fallbackTag, null, fallbackStr) } }})
CSR
的生命周期与 SSR
的生命周期是有差异的,我们可以利用这些差异来达到我们的目的,也就是利用了 onMounted
钩子只会在客户端执行这一特性。
我们创建了一个标记变量
mounted
,初始值为false
,并且仅在客户端渲染时将其设置为true
,这意味着,在服务端渲染的时候,<ClientOnly>
组件的插槽内容不会被渲染。而在客户端渲染的时候,只有等mounted
钩子触发之后才会渲染<ClientOnly>
组件的插槽内容。这样就实现了被<ClientOnly>
组件包裹的内容仅会在客户端被渲染。
另外,<ClientOnly>
组件并不会导致客户端激活失败,hyr,因为在客户端激活的时候,mounted钩子还没有触发,所以服务端与客户端渲染内容一致,即什么都不渲染。等激活完成,且 mounted钩子触发执行之后,才会在客户端将<ClientOnly>
组件的插槽内容渲染出来。–《Vue.js 设计与实现》
- 当
mounted === true
时,也就是客户端渲染时,<ClientOnly>
组件的默认插槽内容会被渲染; - 当
mounted === false
时,也就是服务端渲染时,<ClientOnly>
组件的 fallback插槽 或 placeholder插槽 或 fallback Prop 或 placeholder Prop 内容会被渲染;
本文转自: https://www.wujingquan.com/posts/fb124d0f.html
本站仅做收录,版权归原作者所有。