Nuxt.js 中的“文档未定义”
Posted
技术标签:
【中文标题】Nuxt.js 中的“文档未定义”【英文标题】:"document is not defined" in Nuxt.js 【发布时间】:2018-02-13 23:03:02 【问题描述】:我正在尝试在 Vue 组件中使用 Choices.js。组件编译成功,但随后触发错误:
[vue-router] 无法解析异步组件默认值: ReferenceError: 文档未定义
在我看到的浏览器中:
ReferenceError 文档未定义
我认为这与 Nuxt.js 中的 s-s-r 有关吗?我只需要 Choices.js 在客户端上运行,因为我猜这是客户端唯一的方面。
nuxt.config.js
build:
vendor: ['choices.js']
AppCountrySelect.vue
<script>
import Choices from 'choices.js'
export default
name: 'CountrySelect',
created ()
console.log(this.$refs, Choices)
const choices = new Choices(this.$refs.select)
console.log(choices)
</script>
在经典的 Vue 中,这可以正常工作,所以我仍然非常了解如何让 Nuxt.js 以这种方式工作。
有什么想法我哪里出错了吗?
谢谢。
【问题讨论】:
【参考方案1】:启动 Nuxt 项目时这是一个常见错误 ;-)
Choices.js 库仅适用于客户端!所以 Nuxt 尝试从服务器端渲染,但是从 Node.js window.document
不存在,那么你有一个错误。
注意:window.document
只能在浏览器渲染器中使用。
由于Nuxt 1.0.0 RC7,您可以使用<no-s-s-r>
元素来允许您的组件仅用于客户端。
<template>
<div>
<no-s-s-r placeholder="loading...">
<your-component>
</no-s-s-r>
</div>
</template>
看看这里的官方例子:https://github.com/nuxt/nuxt.js/blob/dev/examples/no-s-s-r/pages/index.vue
更新:
由于Nuxt >= 2.9.0,您必须使用<client-only>
元素而不是<no-s-s-r>
:
<template>
<div>
<client-only placeholder="loading...">
<your-component>
</client-only>
</div>
</template>
要了解更多信息,请参阅 nuxt 文档:https://nuxtjs.org/docs/2.x/features/nuxt-components#the-client-only-component
【讨论】:
谢谢!知道如何使用 s-s-r 输出元素本身吗?例如,一些 JS 需要在客户端为选择列表执行操作,但我仍然希望在服务器上呈现实际的选择列表。<your-component />
文件应该是什么样子?我有YourComponent.vue:<template><div></div></template> <script> import Plotly from 'plotly.js/dist/plotly' export default </script>
,它仍然以document is not defined
结束
nuxtjs.org/guide/plugins#client-side-only plugins: [ src: '~/plugins/vue-notifications', mode: 'client' ]
我会建议那些仍在努力寻找解决方案的人。
@JeffBluemel 您的解决方案拯救了我的一天。我必须在我的 nuxt.config.js src: '~/plugins/vue-izitoast', mode: 'client'
中添加这个
@JeffBluemel,在为解决方案敲了半天之后,您的解决方案是唯一对我有用的解决方案。我确实尝试了我在互联网上可以找到的所有内容。【参考方案2】:
接受的答案(虽然正确)太短了,我无法理解和正确使用它,所以我写了一个更详细的版本。我一直在寻找一种使用plotly.js + nuxt.js的方法,但是应该和OP的Choice.js + nuxt.js的问题一样。
MyComponent.vue
<template>
<div>
<client-only>
<my-chart></my-chart>
</client-only>
</div>
</template>
<script>
export default
components:
// this different (webpack) import did the trick together with <no-s-s-r>:
'my-chart': () => import('@/components/MyChart.vue')
</script>
MyChart.vue
<template>
<div>
</div>
</template>
<script>
import Plotly from 'plotly.js/dist/plotly'
export default
mounted ()
// exists only on client:
console.log(Plotly)
,
components:
Plotly
</script>
更新:在 Nuxt v>2.9.0 中有 <client-only>
标签而不是 <no-s-s-r>,请参阅 @Kaz 的评论。
【讨论】:
这在我使用 evodiaaut.github.io/vue-marquee-text-component 时有效。大多数情况下 no-s-s-r 标记就足够了,但是有了这个库,我必须按照上面提到的方式导入。 @michal。你能解释一下这种导入背后的原因吗 @BaldeepSinghKwatra 不幸的是,据我所知,我通过反复试验得出了这个解决方案 如果您使用的是 Nuxt 版本的 > v2.9.0,请使用<client-only>
而不是 <no-s-s-r>
。由于 <no-s-s-r>
已从 Nuxt v2.9.0 弃用【参考方案3】:
您需要将其添加为插件,然后为其禁用 s-s-r。
因为文档和窗口没有在服务器端定义。
你的 nuxt.config.js 应该如下所示
plugins: [
src: '~/plugins/choices.js' // both sides
src: '~/plugins/client-only.js', mode: 'client' , // only on client side
src: '~/plugins/server-only.js', mode: 'server' // only on server side
],
【讨论】:
现在语法看起来像这样 src: '~/plugins/client-only.js', mode: 'client' , // 仅在客户端 src: '~/plugins/ server-only.js', mode: 'server' // 只在服务器端 感谢指针@ArifIkhsanudin 我刚刚更新了答案。【参考方案4】:我发现现在 no-s-s-r 被替换了,我正在使用 echart 并且有同样的问题,但现在它可以工作了!
<client-only>
<chart-component></chart-component>
</client-only>
【讨论】:
<no-s-s-r>
从 Nuxt 版本 v2.9.0 中弃用。【参考方案5】:
lightgallery.js 添加模式时出现此错误:'client' 似乎有帮助
nuxt.config.js
plugins: [
src: '~/plugins/lightgallery.js', mode: 'client'
],
插件/lightgallery.js
import Vue from 'vue'
import lightGallery from 'lightgallery.js/dist/js/lightgallery.min.js'
import 'lightgallery.js/dist/css/lightgallery.min.css'
Vue.use(lightGallery)
ImageGallery.vue
<template>
<section class="image-gallery-container">
<div class="image-gallery-row">
<div
ref="lightgallery"
class="image-gallery"
>
<a
v-for="image in group.images"
:key="image.mediaItemUrl"
:href="image.mediaItemUrl"
class="image-gallery__link"
>
<img
:src="image.sourceUrl"
:
class="image-gallery__image"
>
</a>
</div>
</div>
</section>
</template>
<script>
export default
name: 'ImageGallery',
props:
group:
type: Object,
required: true
,
mounted()
let vm = this;
if (this.group && vm.$refs.lightgallery !== 'undefined')
window.lightGallery(this.$refs.lightgallery,
cssEasing: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)'
);
</script>
【讨论】:
【参考方案6】:<script>
import Choices from 'choices.js'
export default
name: 'CountrySelect',
created ()
if(process.client)
console.log(this.$refs, Choices)
const choices = new Choices(this.$refs.select)
console.log(choices)
</script>
我想这应该会有所帮助,nuxt 在服务器上渲染后会触及计算的内部,并且将定义窗口
【讨论】:
【参考方案7】:这个帖子有点老了,但我会在这里留下我的解决方案,所以也许有人会觉得它有用。
我最近在使用 vue-star-rating
和其他几个插件时遇到了类似的问题。
可以根据插件名称、导入/使用设置遵循和调整以下步骤:
-
转到您的插件文件夹并创建新的
js
文件,在本例中为vue-star-rating.js
,然后将其编辑为setup the plugin:
import Vue from 'vue'
import VueStarRating from 'vue-star-rating'
Vue.component('vue-star-rating', VueStarRating); //<--- the name you used to register the plugin will be the same to use when in the component (vue-star-rating)
-
转到您的
nuxt.config.js
文件并添加plugin:
plugins: [
src: '~/plugins/vue-star-rating', // <--- file name
mode: 'client'
,
//you can simply keep adding plugins like this:
src: '~/plugins/vue-slider-component',
mode: 'client'
]
-
现在您可以在应用程序的任何位置使用该插件了。但是,要做到这一点,您需要将其包装在容器
<client-only>
中。示例:
<client-only placeholder="loading...">
<vue-star-rating />
</client-only>
注意事项:
您不需要在本地向组件导入任何内容,只需像上面那样使用它就可以解决问题。
请确保在第 1 步和第 3 步这两个地方都以相同的方式命名插件。在这种情况下,它将是 vue-star-rating
。
【讨论】:
【参考方案8】:如果你还想做,可以这样取document对象:
const d = typeof document === 'undefined' ? null : document
【讨论】:
我不确定这是否能解决问题。以上是关于Nuxt.js 中的“文档未定义”的主要内容,如果未能解决你的问题,请参考以下文章
Webpack:ReferenceError:文档未定义[关闭]
如何在 Nuxt.js 中使用 CKEditor - 未定义窗口错误