如何在Nuxt中修复navigator / window / document未定义问题

5

我试图在Nuxt应用程序中确定用户代理和Retina信息。 但是该应用程序会抛出错误并显示navigator / window未定义。 如何在nuxt应用程序内获取这些信息?

const userAgent = navigator.userAgent.toLowerCase()
const isAndroid = userAgent.includes('android')

isRetina() {
  let mediaQuery
  if (typeof window !== 'undefined' && window !== null) {
    mediaQuery =
      '(-webkit-min-device-pixel-ratio: 1.25), (min--moz-device-pixel-ratio: 1.25), (-o-min-device-pixel-ratio: 5/4), (min-resolution: 1.25dppx)'
    if (window.devicePixelRatio > 1.25) {
      return true
    }
    if (window.matchMedia && window.matchMedia(mediaQuery).matches) {
      return true
    }
  }
  return false
}

嗨,由于某种原因,即使按照您提到的步骤进行操作,它似乎仍然无法正常工作,并且我收到了“document is not defined”错误。我已经在这里发布了我的问题,您能帮我解决吗?https://dev59.com/Cqv2oIgBc1ULPQZFUV_i - BATMAN_2008
1个回答

14

这是解决问题的方案:

  • navigator未定义
  • window未定义
  • document未定义

这里有一个例子,展示了如何包装你的逻辑JS代码:
<script>
import { jsPlumb } from 'jsplumb' // client-side library only, no SSR support

export default {
  mounted() {
    if (process.client) {
      // your JS code here like >> jsPlumb.ready(function () {})
    }
  },
}
</script>

如下所示:https://nuxtjs.org/docs/2.x/internals-glossary/context PS: mounted + process.client 有点多余,因为mounted只在客户端上运行。
此外,如果您希望组件仅在客户端渲染,则将其包装在<client-only>中也是一个好主意。
<template>
  <div>
    <p>this will be rendered on both: server + client</p>
    
    <client-only>
      <p>this one will only be rendered on client</p>
    </client-only>
  <div>
</template>

这个的文档在这里:https://nuxtjs.org/docs/2.x/features/nuxt-components/#the-client-only-component 注意,client-only 标签只会跳过渲染,但不会跳过执行,详细解释请看 这里
一些包在导入时不支持SSR,你可以选择以下方式之一:
  • 使用动态导入进行条件判断(如果该库稍后需要使用)
  • 像这样直接导入(如果您想加载组件,如vue-editor
export default {
  components: {
    [process.client && 'VueEditor']: () => import('vue2-editor'),
  }
}

使用这种语法,可以给组件分配一个名称吗?(我正在尝试在VueTouch中使用这个技巧,但是必须将其命名为v-touch才能使其正常工作) - Joe82
@Joe82 [process.client && 'VTouch'] ... 应该可以解决问题。 - kissu
使用[process.client && 'VTouch'],我会得到无法挂载组件:未定义模板或渲染函数。的错误提示。而使用[process.client && 'VueTouch']则会得到未知的自定义元素:<v-touch> - 您是否正确注册了组件?对于递归组件,请确保提供“name”选项。的错误提示。 - Joe82
1
@Joe82 看起来 vue-touch 已经不兼容/维护了:https://github.com/vuejs/vue-touch。你是在谈论另一个包吗?随时打开一个新问题并提到这个答案。我会更深入地帮助你的。 :) - kissu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接