之前有做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()
}
})
好啦, 今天的分享到此结束, 祝大家周末愉快, 玩的开心