You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

63 lines
1.6 KiB

<script lang="ts">
import {
cloneVNode,
createElementBlock,
defineComponent,
getCurrentInstance,
h,
InjectionKey,
onMounted,
provide,
shallowRef,
SlotsType,
VNode,
} from "vue";
export const clientOnlySymbol: InjectionKey<boolean> =
Symbol.for("nuxt:client-only");
export default defineComponent({
name: "ClientOnly",
inheritAttrs: false,
props: ["fallback", "placeholder", "placeholderTag", "fallbackTag"],
...(import.meta.env.DEV && {
slots: Object as SlotsType<{
default?: () => VNode[];
/**
* Specify a content to be rendered on the server and displayed until `<ClientOnly>` is mounted in the browser.
*/
fallback?: () => VNode[];
placeholder?: () => VNode[];
}>,
}),
setup(props, { slots, attrs }) {
const mounted = shallowRef(false);
onMounted(() => {
mounted.value = true;
});
// 这里没什么用,先去掉
// const vm = getCurrentInstance();
// if (vm) {
// vm._nuxtClientOnly = true;
// }
provide(clientOnlySymbol, true);
return () => {
if (mounted.value) {
const vnodes = slots.default?.();
if (vnodes && vnodes.length === 1) {
return [cloneVNode(vnodes[0]!, attrs)];
}
return vnodes;
}
const slot = slots.fallback || slots.placeholder;
if (slot) {
return h(slot);
}
const fallbackStr = props.fallback || props.placeholder || "";
const fallbackTag = props.fallbackTag || props.placeholderTag || "span";
return createElementBlock(fallbackTag, attrs, fallbackStr);
};
},
});
</script>