动态加载js与css文件

背景


在前端日常开发中,肯定会遇到这样的需求场景:一个使用频率很低的功能引入了较大的第三方SDK,且第三方SDK没有提供相应的npm包,无法按需引入,只能在index.html中使用标签的方式引入,导致项目启动的时候需要加载较多的文件,带来了首屏渲染的时间延长。当然也可以使用async与defer属性告诉浏览器延迟执行,但还是会浪费一定的加载资源。

所以可以采用资源的动态加载,只有在需要的时候去动态加载相应的资源文件。

实现


动态加载js

实现思想:

  1. 使用createElement创建DOM元素

  1. 设置type与src

  1. 将DOM元素添加到body中

  1. 监听加载成功与失败执行相应的回调函数


export function loadJs(srcUrl) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = srcUrl
    document.body.appendChild(script)
    script.onload = () => {
      resolve()
    }
    script.onerror = (err) => {
      reject(err)
    }
  })
}

动态创建时,可能遇到已经创建过该元素并添加到body中,重复创建的有点浪费(DOM的创建很浪费资源),所以在创建时判断当前文件是否已经存在


...
// 判断当前js是否已经加载过
const scriptNodes = [].slice.call(document.querySelectorAll('script')).map(item => item.src)
if (scriptNodes.includes(srcUrl)) return resolve()
...

完整代码


/**
 * 动态加载js文件
 * @param {*} srcUrl 文件地址
 * @returns Promise
 */
export function loadJs(srcUrl) {
  return new Promise((resolve, reject) => {
    // 判断当前js是否已经加载过
    const scriptNodes = [].slice.call(document.querySelectorAll('script')).map(item => item.src)
    if (scriptNodes.includes(srcUrl)) return resolve()

    const script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = srcUrl
    document.body.appendChild(script)
    script.onload = () => {
      resolve()
    }
    script.onerror = (err) => {
      reject(err)
    }
  })
}

动态加载css


/**
 * 动态加载js文件
 * @param {*} hrefUrl 文件地址
 * @returns Promise
 */
export function loadCss(hrefUrl) {
  return new Promise((resolve, reject) => {
    // 判断当前css是否已经加载过
    const linkNodes = [].slice.call(document.querySelectorAll('link')).map(item => item.href)
    if (linkNodes.includes(hrefUrl)) return resolve()

    const link = document.createElement('link')
    link.type = 'text/css'
    link.rel = 'stylesheet'
    link.href = hrefUrl
    document.head.appendChild(link)
    link.onload = () => {
      resolve()
    }
    link.onerror = (err) => {
      reject(err)
    }
  })
}

动态加载多个文件


/**
 * 动态加载多个文件
 * @param {*} jsList js文件地址列表
 * @param {*} cssList css文件地址列表
 * @returns Promise
 */
export function asyncLoad(jsList, cssList) {
  return new Promise((resolve, reject) => {
    const jsPromiseList = []
    const cssPromiseList = []
    jsList.forEach(item => {
      jsPromiseList.push(loadJs(item))
    })
    cssList.forEach(item => {
      cssPromiseList.push(loadCss(item))
    })
    Promise.all([
      ...cssPromiseList,
      ...jsPromiseList
    ]).then(_ => resolve()).catch(reject)
  })
}

使用



loadJs('js_url').then(res => ...)
loadCss('css_url').then(res => ...)
asyncLoad(['js_url', ...], ['css_url', ...]).then(res => ...)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑狼传说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值