[英]"document is not defined" in Nuxt.js
我正在嘗試在 Vue 組件中使用Choices.js 。 組件編譯成功,但隨后觸發錯誤:
[vue-router] 無法解析異步組件默認值:ReferenceError:文檔未定義
在瀏覽器中我看到:
ReferenceError 文檔未定義
我認為這與 Nuxt.js 中的 SSR 有關嗎? 我只需要 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 以這種方式工作。
我哪里出錯了有什么想法嗎?
謝謝。
當您啟動 Nuxt 項目時,這是一個常見錯誤;-)
Choices.js庫僅適用於客戶端! 所以 Nuxt 嘗試從服務器端渲染,但是從 Node.js 的window.document
不存在,那么你有一個錯誤。
注意: window.document
只能從瀏覽器渲染器獲得。
從Nuxt 1.0.0 RC7 開始,您可以使用<no-ssr>
元素來允許您的組件僅用於客戶端。
<template>
<div>
<no-ssr placeholder="loading...">
<your-component>
</no-ssr>
</div>
</template>
看看這里的官方示例: https ://github.com/nuxt/nuxt.js/blob/dev/examples/no-ssr/pages/index.vue
更新:
由於Nuxt >= 2.9.0 ,您必須使用<client-only>
元素而不是<no-ssr>
:
<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
接受的答案(雖然正確)太短了,我無法理解和正確使用它,所以我寫了一個更詳細的版本。 我一直在尋找一種使用plotly.js + nuxt.js的方法,但它應該與OP的Choice.js + nuxt.js問題相同。
我的組件.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-ssr>:
'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-ssr>
,請參閱@Kaz 的評論。
您需要將其添加為插件,然后為其禁用 SSR。
由於文檔和窗口未在服務器端定義。
您的 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
],
我發現現在 no-ssr 被替換為 ,我正在使用 echart 並且有同樣的問題,但現在它可以工作了!
<client-only>
<chart-component></chart-component>
</client-only>
我在 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)
圖片庫.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"
:alt="image.altText"
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>
<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 在服務器上渲染后會觸及計算的內部,並且將定義窗口
這個線程有點老了,但我會把我的解決方案留在這里,所以也許有人會覺得它有用。
我最近對vue-star-rating
和其他幾個插件也有類似的問題。
可以根據插件名稱、導入/使用設置遵循和調整以下步驟:
js
文件,在本例中vue-star-rating.js
,然后對其進行編輯以設置插件: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
文件並添加插件: 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
。
如果您仍然想這樣做,可以通過以下方式獲取文檔對象:
const d = typeof document === 'undefined' ? null : document
為了完整起見,值得一提的是,除了Yusuf Adeyemo 答案中的對象語法(我更喜歡它,因為它將文件與使用方式分開),您還可以將插件設置為僅通過命名文件在客戶端或服務器端運行像這樣:
export default {
plugins: [
'~/plugins/foo.client.js', // only in client side
'~/plugins/bar.server.js', // only in server side
'~/plugins/baz.js' // both client & server
]
}
src: https ://nuxtjs.org/docs/directory-structure/plugins/#client-or-server-side-only
除了這里的所有答案之外,您還可以面對一些其他與 SSR 不兼容的開箱即用的軟件包(例如您的情況),並且需要一些技巧才能正常工作。 這是我的詳細回答。
TLDR 是您有時需要:
process.client
<client-only>
標簽(小心,它不會渲染但仍然執行里面的代碼)const Ace = await import('ace-builds/src-noconflict/ace')
components: { [process.client && 'VueEditor']: () => import('vue2-editor') }
有了所有這些,您幾乎可以應對所有可能的情況。
我試圖在created
的鈎子中訪問document
,所以當我將邏輯從created
的鈎子移動到mounted
的鈎子時,我的問題就解決了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.