nuxt Window 或 Document未定義解決方案

概述

在用nuxt開發服務端渲染項目並引入第三方庫的時候,常常會遇到window或document未定義的狀況,緣由是這個第三方庫裏面用到了window或者document,而後在服務端打包的時候,node環境並無window或者document,因此就報了window或document未定義的錯誤。css

並且,咱們在引入第三方庫的時候,並不但願把第三方庫打包進app.js,而是但願這個第三方庫只在須要的頁面才加載。html

下面以tinymce這個第三方庫爲例,記錄我在nuxt.js框架中的實現方法,供之後開發時參考,相信對其餘人也有用。vue

官網方法

咱們不能把tinymce放到plugin裏面去引入,由於這樣會引入到全局js裏面去。node

nuxt官網介紹了一種方法:Window 或 Document 對象未定義?,可是寫的很簡略,我這裏詳細說明一下。webpack

首先咱們在要引入的blog.vue文件中,經過判斷是不是客戶端來選擇性的加載tinymce這個庫:web

let tinymce;
if (process.client) {
  tinymce = require('tinymce/tinymce');

  // A theme is also required
  require('tinymce/themes/silver/theme');

  // Any plugins you want to use has to be imported
  require('tinymce/plugins/advlist');
  require('tinymce/plugins/wordcount');
  require('tinymce/plugins/autolink');
  require('tinymce/plugins/autosave');
  require('tinymce/plugins/charmap');
  require('tinymce/plugins/codesample');
  require('tinymce/plugins/contextmenu');
  require('tinymce/plugins/emoticons');
  require('tinymce/plugins/fullscreen');
  require('tinymce/plugins/hr');
  require('tinymce/plugins/imagetools');
  require('tinymce/plugins/insertdatetime');
  require('tinymce/plugins/link');
  require('tinymce/plugins/media');
  require('tinymce/plugins/noneditable');
  require('tinymce/plugins/paste');
  require('tinymce/plugins/print');
  require('tinymce/plugins/searchreplace');
  require('tinymce/plugins/tabfocus');
  require('tinymce/plugins/template');
  require('tinymce/plugins/textpattern');
  require('tinymce/plugins/visualblocks');
  require('tinymce/plugins/anchor');
  require('tinymce/plugins/autoresize');
  require('tinymce/plugins/bbcode');
  require('tinymce/plugins/code');
  require('tinymce/plugins/colorpicker');
  require('tinymce/plugins/directionality');
  require('tinymce/plugins/fullpage');
  require('tinymce/plugins/help');
  require('tinymce/plugins/image');
  require('tinymce/plugins/importcss');
  require('tinymce/plugins/legacyoutput');
  require('tinymce/plugins/lists');
  require('tinymce/plugins/nonbreaking');
  require('tinymce/plugins/pagebreak');
  require('tinymce/plugins/preview');
  require('tinymce/plugins/save');
  require('tinymce/plugins/spellchecker');
  require('tinymce/plugins/table');
  require('tinymce/plugins/textcolor');
  require('tinymce/plugins/toc');
  require('tinymce/plugins/visualchars');

  require('tinymce/skins/lightgray/skin.min.css';
}

這樣,在服務端就不會引入這些庫,只會在客戶端引入。可是服務端沒有引入的話,相關js在執行的時候會報不存在的錯誤,這裏就須要再用process.client判斷一下環境再執行。示例以下:app

if (process.client) {
  tinymce.init({
    ...options,
    ...this.otherOptions,
    language: this.language,
  });
)

script方法

有時候咱們但願用引入tinymce.js的方法來引入,而不用webpack打包的方式。這個時候咱們須要在blog.vue裏面加上以下代碼便可:框架

export default {
  name: 'Blog',
  layout: 'blank',
  head: {
    script: [
      { src: '/tinymce.5.0.4/tinymce.min.js' },
    ],
  },
}

其中上面src的路徑是static文件夾的絕對路徑。ui

按照上述的方法會有一個問題,就是執行下面的代碼的時候,即便用了process.client,但仍是會報tinymce不存在的錯誤:this

if (process.client) {
  tinymce.init({
    ...options,
    ...this.otherOptions,
    language: this.language,
  });
)

緣由是,客戶端打包的時候,tinymce確實是沒有定義的。因此這裏改爲以下形式便可:

if (process.client) {
  window.tinymce.init({
    ...options,
    ...this.otherOptions,
    language: this.language,
  });
)

其它

nuxt有一個組件是no-ssr組件,因此上面的html最好用no-ssr包起來,否則會報tinymce組件沒有定義的錯誤:

<no-ssr placeholder="Loading...">
  <tinymce
    id="myTinymce"
    v-model="content"
    :height="600"
  />
</no-ssr>
相關文章
相關標籤/搜索