立诚勿怠,格物致知
It's all about connecting the dots

loadScripts方法

北京前端同事有个项目里用了ace-admin这个管理平台框架,不太喜欢这个框架,不过在里面发现了一段异步加载js脚本文件的代码,修改了一下贴到这里,以后自己项目里也可以用:

export function ready (optionalScriptsDependencies, cb) {
  if (arguments.length === 1) {
    waitForReady(cb);
  } else if (arguments.length === 2) {
    loadScripts(optionalScriptsDependencies, () => {
      waitForReady(cb);
    });
  }
}

function waitForReady (cb) {
  $(document).ready(function () {
    cb && cb();
  });
}

// ajaxLoadedScripts要放到loadScripts外才能起到全局统计的作用
const ajaxLoadedScripts = {};
function loadScripts (scripts, callback) {
  $.ajaxPrefilter('script', (opts) => { opts.cache = true; });
  setTimeout(() => {
    function finishLoading () {
      typeof callback === 'function' && callback();
    }

    let deferredCount = 0;
    let resolved = 0;
    for (let i = 0; i < scripts.length; i++) {
      if (scripts[i]) {
        (() => {
          const scriptName = 'js-' + scripts[i].replace(/[^\w\d-]/g, '-').replace(/--/g, '-');
          ajaxLoadedScripts[scriptName] !== true && deferredCount++;
        })();
      }
    }

    function nextScript (index) {
      index += 1;
      if (index < scripts.length) {
        loadScript(index);
      } else {
        finishLoading();
      }
    }

    function loadScript (index) {
      index = index || 0;
      if (!scripts[index]) {
        return nextScript(index);
      }

      const scriptName = 'js-' + scripts[index].replace(/[^\w\d-]/g, '-').replace(/--/g, '-');
      // 只加载目前为止没有加载过的脚本
      if (ajaxLoadedScripts[scriptName] !== true) {
        $.getScript(scripts[index]).done(() => {
          ajaxLoadedScripts[scriptName] = true;
        }).complete(() => {
          ++resolved >= deferredCount ? finishLoading() : nextScript(index);
        });
      } else {
        nextScript(index);
      }
    }

    deferredCount > 0 ? loadScript() : finishLoading();
  }, 10);
}

使用方法很简单,碰到有js文件依赖的时候,这样使用ready方法:

ready([
  '../assets/js/jquery.validate.js',
], () => {
  // 这时依赖的js脚本文件已经加载完毕了,document ready后要执行的代码放在此处
});

如果没有js文件依赖的话,这样使用ready方法:

ready(() => {
  // document ready后要执行的代码放在此处
});

下面是根据以前自己写过的方法封装一下得到的代码,作用差不多(没像上面的例子那样判断脚本是否已加载过,不过用document.write生成script标签加载js文件的话,浏览器自己也会做缓存处理的,问题不大吧-_-):

function loadAsyncScripts(scripts, callback) {
  const scriptsLength = scripts.length;
  scripts.forEach(item => loadAsyncScript(item, checkWhetherToExecuteCallback.bind(null, scriptsLength, callback)));
}

let counter = 0;
function checkWhetherToExecuteCallback (scriptsLength, cb) {
  ++counter === scriptsLength && cb();
}

function loadAsyncScript(src, callback) {
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.setAttribute('type', 'text/javascript');
  script.setAttribute('src', src);
  script.setAttribute('async', true);
  script.setAttribute('defer', true);
  head.appendChild(script);

  if (document.all) {
    script.onreadystatechange = function () {
      var state = this.readyState;
      if (state === 'loaded' || state === 'complete') {
        callback();
      }
    }
  } else {
    script.onload = function () {
      callback();
    }
  }
}

 

赞(0) 打赏
文章名称:《loadScripts方法》
文章链接:https://www.orzzone.com/loadscripts-method.html
商业联系:yakima.public@gmail.com

本站大部分文章为原创或编译而来,对于本站版权文章,未经许可不得用于商业目的,非商业性转载请以链接形式标注原文出处。
本站内容仅供个人学习交流,不做为任何投资、建议的参考依据,因此产生的问题需自行承担。

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力提供更多优质内容!

支付宝扫一扫打赏

微信扫一扫打赏

登录

找回密码

注册