vue项目如何动态引入js

1,493 阅读2分钟

之前有做app嵌套H5的项目, 其中有调用客户端设置头部, 上传文件, 打开新view之类的方法, 所以引入了客户端封装的js, 放在了vue项目的static文件夹下面, 然后直接在index.html文件夹下用script标签引入即可.

突然某一天项目经理说之前的H5页面要嵌入钉钉. 钉钉端肯定是没有客户端的方法喽, 直接引入钉钉的H5微应用js就行了. 想法是很好的但是现实很残酷, 调用钉钉免登接口dd.runtime.permission.requestAuthCode怎么都调取不成功, 找不到问题的情况下,只能采用排除法了. 尝试了很多方法, 终于在注掉引入客户端的三个js文件后, 钉钉端的方法调用成功了. 那就是说这两个js文件是有冲突的不能共存, 既然找到了问题的根源想办法去解决问题就行

第一步:区分环境

这个很好解决直接调用navigator.userAgent

if (navigator.userAgent.indexOf('AliApp') > -1) {
    /**
    引入钉钉的js
    */
  } else {
    /**
    引入客户端的js
    */
  }

第二步:如何动态引入js

function addScript (url) {
    const scriptInfo = document.createElement('script')
    scriptInfo.type = 'text/javascript'
    scriptInfo.src = url
    document.body.appendChild(scriptInfo)
}

我们可以将加载js的方法使用promise进行优化, 将加载完成的事件传递出去, 保证在调用里面的方法时候js已经加载完成

function addScript (url) {
  return new Promise(function (resolve, reject) {
    const scriptInfo = document.createElement('script')
    scriptInfo.type = 'text/javascript'
    scriptInfo.src = url
    document.body.appendChild(scriptInfo)
    scriptInfo.onload = scriptInfo.onreadystatechange = function () {
      if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
        scriptInfo.onload = scriptInfo.onreadystatechange = null
        resolve()
      }
    }
  })
}

第三步:如何保证在页面加载之前保证js引入

这里可以使用router.beforEach对路由进行一个拦截

router.beforeEach((to, from, next) => {
  // isLoadJs 为是否已经加载完成js
  if (!isLoadJs) {
    // 加载js的代码
  } else {
    next()
  }
})

这样就是实现了js的动态引入,,并保证其在页面加载之前已经加载完成

下面是main.js中动态引入js的完整代码

// 是否加载完所需js
let isLoadJs = false

// 动态加载js的方法
function addScript (url) {
  return new Promise(function (resolve, reject) {
    const scriptInfo = document.createElement('script')
    scriptInfo.type = 'text/javascript'
    scriptInfo.src = url
    document.body.appendChild(scriptInfo)
    scriptInfo.onload = scriptInfo.onreadystatechange = function () {
      if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
        scriptInfo.onload = scriptInfo.onreadystatechange = null
        // 保证js加载完成后,将结果传递出去
        resolve()
      }
    }
  })
}

// 区分钉钉环境还是其他环境加载相应js
function loadScript (callback) {
  if (navigator.userAgent.indexOf('AliApp') > -1) {
    addScript('https://g.alicdn.com/dingding/dingtalk-jsapi/3.0.12/dingtalk.open.js').then(() => {
      isLoadJs = true
      callback()
    })
  } else {
  // 使用Promise.all方法保证三个js文件都加载完成后在进行下一步操作
    Promise.all([
      addScript('xxxxxxx1js')
      addScript('xxxxxxx2js')
      addScript('xxxxxxx3js')
    ]).then(() => {
      isLoadJs = true
      callback()
    })
  }
}

// 进行路由拦截还未加载js的加载完成以后再之心next(),如果有放行
router.beforeEach((to, from, next) => {
  if (!isLoadJs) {
    loadScript(next)
  } else {
    next()
  }
})

好啦, 今天的分享到此结束, 祝大家周末愉快, 玩的开心

image.png