zoukankan      html  css  js  c++  java
  • javascript 异步模块加载 简易实现

      在javascript是没有类似java或其他语言的模块概念的,因此也不可能通过import或using等关键字来引用模块,这样造成了复杂项目中前端代码混乱,变量互相影响等。

      因此在复杂项目中引入AMD的概念,AMD:全称是Asynchronous Module Definition,即异步模块加载机制。通过AMD可以不需要在页面中手动添加<script>来引用脚本,而通过定义依赖自动加载模块脚本,接下来的代码将讲解如何实现建议的AMD模块,如果需要查看比较详细的实现可以下载requirejs源码。

    简易实现整体思路:

    1.将模块名及模块文件地址存入内存

    2.通过define方法将模块名及模块依赖关系以及模块实现代码存入内存

    3.require方法通过loadscript方法将需要依赖的模块代码导入并执行define方法存入内存,模块通过入参传入实际代码中,从而完成模块加载。

    1.定义模块:

    实现模块的定义,并将模块定义存储。

               /**
               * 
               * @param id 模块名
                 * @param deps 依赖模块
                 * @param factory 模块实现
                 */
                define: function (id, deps, factory) {

    在定义模块中,需要将模块名,模块依赖,模块代码存储至内存中

               /**
               * 
               * @param id 模块名
                 * @param deps 依赖模块
                 * @param factory 模块实现
                 */
                define: function (id, deps, factory) {
                    // 模块是否存在
                    if (modules[id]) throw new Error("module:" + id + "已经存在!");
                    if (arguments.length > 2) {
                        modules[id] = {
                            id: id,
                            deps: deps,
                            factory: factory
                        }
                    }
                    else if (arguments.length == 2) {
                        modules[id] = {
                            id: id,
                            factory: deps
                        }
                    }
                    else {
                        throw new Error("module:参数有误!");
                    }
                },

    2.引用模块:

    输入依赖模块名,执行代码,代码示例如下:

               /**
                * 异步导入模块
                 * @param deps 依赖模块
                 * @param callback
                * @returns {{}}
                */
                require: function (deps, callback) {
                    // 插入脚本
                    deps = [].slice.call(deps);
                    // 获取依赖脚本
                    loadScript(deps, buildModule, callback);
                },

    详细步骤:

    首先需要从依赖的文件夹中导入脚本,

            /**
            * 从外部加载js
            * @param deps 依赖模块
             * @param buildModule 创建模块方法
             * @param callback
            */
            function loadScript(deps, buildModule, callback) {
                var depJsCounter = 0;
                deps.forEach(function (dep) {
                    var script = document.createElement("script")
                    script.type = "text/javascript";
                    script.src = configs[dep];
                    document.getElementsByTagName("head")[0].appendChild(script);
                    script.onload = function () {
                        // 依赖js加载计数标记
                        depJsCounter++;
                        if (depJsCounter == deps.length) {
                            buildModule(deps, callback)();
                        }
                    };
                });
    
            }

    构建模块,从全局module中取出依赖模块,将依赖模块作为入参注入到现有模块,最后执行现有模块

            /**
             * 创建模块
             * @param deps 依赖模块
             * @param callback
             * @returns {Function}
             */
            var buildModule = function (deps, callback) {
                return function () {
                    // 获取依赖模块
                    var args = [];
                    deps = [].slice.call(deps);
                    deps.forEach(function (dep) {
                        var module = modules[dep]
                        if (typeof module.factory === 'function')
                            module.factory = module.factory();
                        args.push(module.factory)
                    })
                    // 将依赖模块注入到callback中
                    var temp = {};
                    callback.apply(temp, args);
                    return temp
                }
            }

    3.注册模块

    注册模块主要将名字与文件路径关联起来,便于从路径中下载js,代码清单如下:

               /**
                 * 注册模块
                 * @param obj
                 */
                config: function (obj) {
                    var path = obj.paths;
                    for (var el in path) {
                        Object.defineProperty(configs, el, {
                            enumerable: false,
                            configurable: false,
                            writable: true,
                            value: path[el]
                        })
                    }
                }
            }

    4.执行实例

    编写模块

    define('module1', function () {
        var module1 = {};
        module1.sayhello = function () {
            return 'hello module1';
        }
        return module1;
    });

    将代码保存js文件并取名module1

    新建html文件,在html中先注册模块,通过require 导入模块,并利用模块编写代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="/demo/01Requirejs/require.js"></script>
    </head>
    <body>
    
    </body>
    </html>
    <script>
    
    require.config({
       paths:{
           module1:'/demo/01Requirejs/module1.js'
       }
    });
    
    require(['module1'],function(module1){
        alert(module1.sayhello());
    })
    
    </script>
  • 相关阅读:
    目标检测网络CenterNet详解(四)
    样本不均衡问题
    目标检测网络Faster RCNN详解(一)
    SpringCloud学习总结(八)——服务调用Feign
    OpenFeign(2020-10-13)
    Feign真正正确的使用方法
    微服务实战SpringCloud之Feign简介及使用
    spring cloud gateway网关和负载均衡框架ribbon实战
    Studio 3T 破解
    JVM 垃圾回收?全面详细安排!
  • 原文地址:https://www.cnblogs.com/vipyoumay/p/4819072.html
Copyright © 2011-2022 走看看