解决nuxt3中scroll组件渲染报错:document is not defined

2023-12-14 19:49:39

现象:

?我敢说这是nuxt3中出现的最让人头痛的问题之一,非常难搞。

原因:被渲染组件中使用了dom原生api,但是它的代码却打包到ssr服务端环境中,众所周知服务端环境(node环境)是没有window/document/navigator这些原生js对象的。

解决办法有三种:

方法一(不推荐): 使用ClientOnly标签把该组件中存在document渲染问题的html部分包裹住

The?<ClientOnly>?component renders its slot only in client-side. To import a component only on the client, register the component in a client-side only plugin.

这种方法不是很推荐,因为这个方法太简单粗暴,严重怀疑会把本不应该做csr的代码打包进浏览器客户端js中,这样减少了服务端渲染的展现量,也加重了客户端的打包体积。

而且每个有问题的组件都要加上ClientOnly标签

方法二(不推荐)、用一个变量isClient来判断是否为浏览器环境,然后用v-if判断是否显示scoll组件,同时在onMount挂载之前通过process.client给isClient赋值。

?<wrap-scroll v-if="isClient" ?class="recommend-content">

?xxxx

interface State extends RecommendResp {?

? isClient: boolean | false;

}

?const state = reactive<State>({?

? ? ? isClient: false

? ? });

? ?onMounted(() => {? ? ??

? ? ? state.isClient = process.client? ? ?

? ? });

这种方法也不是很推荐,因为增加了代码量,而且每个用到scroll组件的页面都要这样添加代码。

方法三(推荐): 从问题根源入手,在scroll组件本身,通过process.client判断是否浏览器环境,是浏览器环境才执行组件代码:

 setup(props, { emit }) {
    if (process.client) { // 仅在浏览器环境才执行组件代码
      const rootRef = ref<HTMLDivElement>(document.createElement("div"));
      const scroll = useScroll(rootRef, props, emit);
      return {
        rootRef,
        scroll,
      };
    }
  },

注意必须是在scroll根组件做浏览器环境判断!

在包装组件wrapper做这种判断没有用!

这样就能从根本解决问题,修改这一个地方就够了!

文章来源:https://blog.csdn.net/jiaohuizhuang6019/article/details/135001688
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。