JavaScript动态加载js和css

动态加载js

参考:javascript 性能优化

function loadScript(url, callback) {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    if (script.readyState) {
        // 处理IE
        script.onreadystatechange = function () {
            if (script.readyState === 'loaded' || script.readyState === 'complete') {
                script.onreadystatechange = null;
                callback();
            }
        }
    } else {
        // 处理其他浏览器的情况
        script.onload = function () {
            callback();
        }
    }
    script.src = url;
    document.body.append(script);
}

// 动态加载js
loadScript('file.js', function () {
  console.log('加载完成');
})

动态加载css

参考: 动态加载 css 方法实现和深入解析


/**
 * @function 动态加载css文件
 * @param {string} options.url -- css资源路径
 * @param {function} options.callback -- 加载后回调函数
 * @param {string} options.id -- link标签id
 */
function loadCss(options) {
    var url = options.url,
        callback = typeof options.callback == 'function' ? options.callback : function () {
        },
        id = options.id,
        node = document.createElement('link'),
        supportOnload = 'onload' in node,
        isOldWebKit = +navigator.userAgent.replace(/.*(?:AppleWebKit|AndroidWebKit)\/?(\d+).*/i, '$1') < 536, // webkit旧内核做特殊处理
        protectNum = 300000; // 阈值10分钟,一秒钟执行pollCss 500次

    node.rel = 'stylesheet';
    node.type = 'text/css';
    node.href = url;
    if (typeof id !== 'undefined') {
        node.id = id;
    }
    document.getElementsByTagName('head')[0].appendChild(node);

    // for Old WebKit and Old Firefox
    if (isOldWebKit || !supportOnload) {
        // Begin after node insertion
        setTimeout(function () {
            pollCss(node, callback, 0);
        }, 1);
        return;
    }

    if (supportOnload) {
        node.onload = onload;
        node.onerror = function () {
            // 加载失败(404)
            onload();
        }
    } else {
        node.onreadystatechange = function () {
            if (/loaded|complete/.test(node.readyState)) {
                onload();
            }
        }
    }

    function onload() {
        // 确保只跑一次下载操作
        node.onload = node.onerror = node.onreadystatechange = null;

        // 清空node引用,在低版本IE,不清除会造成内存泄露
        node = null;

        callback();
    }

    // 循环判断css是否已加载成功
    /*
    * @param node -- link节点
    * @param callback -- 回调函数
    * @param step -- 计步器,避免无限循环
    */
    function pollCss(node, callback, step) {
        var sheet = node.sheet,
            isLoaded;

        step += 1;

        // 保护,大于10分钟,则不再轮询
        if (step > protectNum) {
            isLoaded = true;

            // 清空node引用
            node = null;

            callback();
            return;
        }

        if (isOldWebKit) {
            // for WebKit < 536
            if (sheet) {
                isLoaded = true;
            }
        } else if (sheet) {
            // for Firefox < 9.0
            try {
                if (sheet.cssRules) {
                    isLoaded = true;
                }
            } catch (ex) {
                // 火狐特殊版本,通过特定值获知是否下载成功
                // The value of `ex.name` is changed from "NS_ERROR_DOM_SECURITY_ERR"
                // to "SecurityError" since Firefox 13.0. But Firefox is less than 9.0
                // in here, So it is ok to just rely on "NS_ERROR_DOM_SECURITY_ERR"
                if (ex.name === 'NS_ERROR_DOM_SECURITY_ERR') {
                    isLoaded = true;
                }
            }
        }

        setTimeout(function () {
            if (isLoaded) {
                // 延迟20ms是为了给下载的样式留够渲染的时间
                callback();
            } else {
                pollCss(node, callback, step);
            }
        }, 20);
    }
}

小结

动态加载js和css可以用于一些附加功能的实现,在需要使用时才加载相关资源。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容