vue項目中動態引入遠程(第三方)js和css


將index.html中的遠程js和css設置為可配置的動態加載
 
之前:index.html中寫死了js與css的路徑,每次打包都要修改index.html文件或者用替換的方式將index.html中的網址換為新的要部署地區的網址,給部署人員帶來復雜的操作;開發人員進行部署測試也很不方便。
 
現在:通過Promise實現了異步加載js的方法,將js和css從index.html中提取出來,變成路徑可配置的形式,簡化了部署步驟以及開發測試的工作。
主要解決了vue的mounted階段使用到js中的對象,控制台提示變量未定義的錯誤。因為無論是用document.write還是用原生js直接添加到dom樹上的方法,都是會在mounted掛載階段完成之后再解析js,所以,一直會遇到“XX變量未定義”的錯誤
 
Promise的定義:promise是對異步編程的一種抽象。它是一個代理對象,代表一個必須進行異步處理的函數返回的值或拋出的異常。
 
Q是nodeJs中實現promise的包之一,是nodexJs中比較常用的一個庫。
 
下面來說一說具體實現:
一、安裝Q
npm install q -save
 
二、在項目中的使用:
2.1 創建用於加載js、css的文件
文件名為loadResources.js,文件內容如下:
/**
 * Created by 飛呀 on 2018/1/9.
 */
//加載css與js文件
var Q=require('q');
export default function asyncLoadJs (url) {
  return Q.Promise((resolve, reject) => {
    let srcArr = document.getElementsByTagName("script");
    let hasLoaded = false;
    for (let i=0;i<srcArr.length;i++){//判斷當前js是否加載上
      hasLoaded = (srcArr[i].src==url)?true:false;
    }
    if (hasLoaded) {
      resolve();
      return;
    }
    let script = document.createElement('script')
    script.type = 'text/javascript';
    script.src = url;
    document.body.appendChild(script);
    script.onload = () => {
      resolve();
    }
    script.onerror = () => {
      reject();
    }
  })
}

export function loadCss(url){
  let css = document.createElement('link');
  css.href = url;
  css.rel = 'stylesheet';
  css.type = 'text/css';
  document.head.appendChild(css);
}

export function loadMineMapJs () {
  //加載css
  loadCss( appDomainRoot+"/minemapapi/v1.3/minemap.css");
  loadCss( appDomainRoot+"/minemapapi/v1.3/plugins/draw/minemap-draw.css");
  loadCss( appDomainRoot+"/minemapapi/v1.3/plugins/edit/minemap-edit.css");
  //加載js
  return Q.Promise((resolve, reject) => {
    asyncLoadJs("./static/js/minemap_wmts.js")//開發用
    /*asyncLoadJs(appDomainRoot + "/minemapapi/demo/js/minemap-wmts.js")//部署用*/
      .then(() => {
        return asyncLoadJs(appDomainRoot + "/minemapapi/v1.3/plugins/draw/minemap-draw.js")
      })
      .then(() => {
        return asyncLoadJs(appDomainRoot + "/minemapapi/v1.3/plugins/edit/minemap-edit.js")
      })
      .then(() => {
        resolve()
      })
      .catch(err => {
        reject(err)
      })
  })
}
需要注意的是,loadMineMapJs方法中要加載多個js可以在后面加then方法再次返回asyncLoadJs方法,這是 級聯的用法。
 
2.2 組件中對於異步加載js模塊的使用
引入模塊
  import {loadMineMapJs} from '../globals/loadResources'
緊隨其后,定義一個用於判斷所有js是否加載完成的一個標志
let loadedMineMapJs = false;//是否加載完js
因為loadedMineMapJs這個變量在created階段就要使用到,所以不能放在data里面。
created階段:
    created(){//判斷瀏覽器是否加載過js
      if (!loadedMineMapJs) {
        loadMineMapJs().then(() => {
          loadedMineMapJs = true;
        })
      }
    },
mounted階段:
    mounted(){
      let _this = this;
        //循環判斷是否加載完js
      let interval = setInterval(()=>{
          if(loadedMineMapJs){
            clearInterval(interval);
            _this.controller = new HomeController(_this);
            _this.controller.initMapEdit(null, null, null);
          }
      },100);
    ...
    },
下面這兩句是我會用到js中生成對象的地方,所以需要在js完成后執行
            _this.controller = new HomeController(_this);
            _this.controller.initMapEdit(null, null, null);
2.3 對於網址的配置
在serverConfig下的index.js文件中配置了第一步中用到appDomainRoot(前提是index.js文件在static文件夾下,不會被webpack打包),修改的時候只需要修改appDomainRoot的值即可,變量未定義的問題順利解決。
文件結構:
index.js中配置如下:
let appDomainRoot= 'http://192.168.XX.XX';
這個功能難就難在index.html中引入的js和css會直接在html解析時就引入,一旦使用動態添加到dom樹的js語句(比如document.body.appendChild())的方式添加動態script必然導致瀏覽器在解析到這些js時重新生成dom樹,經測試這種方式會在vue掛載前拼接到index.html中,但是要等到掛載結束才會被解析,所以在掛載階段用到js解析生成的對象會一直出現“變量未定義”的錯誤。
使用document.write()的方式雖然可以實現,但是瀏覽器會輸出警告,大意是瀏覽器正在解析跨域資源,而且有幾條動態js就會警告幾次,而且在控制台占的面積相對較大,所以最好還是不要使用這個方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM