• JS模块加载系统设计V1


    一、require模块

        +function() {
            var path = location.protocol + "//" + location.host +"/Javasript框架设计/common/";
            require.config({
                alias: {
                    "jquery": {
                        src: path + "mass/demo/jquery-1.9.1.min.js",
                        deps: [],//没有依赖可以不写
                        exports: "jQuery" //要从全局作用域抽取的数据
                    }
                }
            });
            require("jquery", function($) {
                alert($)
                alert($("body").length);
                alert("回调调起成功");
                alert($("body").length) //这里不用domReady了
            })
        }()

    以上是源码

    我喜欢以剖析源代码的方式去学一种技术,上面这段代码是标准的requireJs的语句,但是这是mass.js版本的requireJs,下面就来解读源代码:

    var path = location.protocol + "//" + location.host +"/Javasript框架设计/common/"

    这个path是网站的根路径,方便mass寻找Js和css的文件.

      require.config({
                alias: {
                    "jquery": {
                        src: path + "mass/demo/jquery-1.9.1.min.js",
                        deps: [],//没有依赖可以不写
                        exports: "jQuery" //要从全局作用域抽取的数据
                    }
                }
            });

    这段代码主要是记载系统的文件别名机制,通过给想要加载的文件起一个别名,并且指定该文件的路径。下面来看mass是如何实现这个功能的:

        (function() {
            var cur = getCurrentScript(true);
            if (!cur) {//处理window safari的Error没有stack的问题
                cur = $.slice(document.scripts).pop().src;
            }
            var url = cur.replace(/[?#].*/, "");
            kernel = $.config;
            kernel.plugin = {};
            kernel.alias = {};
            basepath = kernel.base = url.slice(0, url.lastIndexOf("/") + 1);
            var scripts = DOC.getElementsByTagName("script");
            for (var i = 0, el; el = scripts[i++]; ) {
                if (el.src === cur) {
                    kernel.nick = el.getAttribute("nick") || "$";
                    break;
                }
            }
            kernel.level = 9;
        })();

    通过这个自执行函数,将$.config函数对象托管给kernel对象

    require.config = kernel;

    然后在将kernel对象托管给require.config对象,require.config其实就是$.config函数对象,也就是说你通过require.config传递的参数,实际都会传递给$.config函数,个人觉得这个设计蛮不错的,当我们以后有新的模块需要进行类似的配置时,也可以通过这种方式,增强了代码的复用性。

    再来看$.config做了什么?

      config: function(settings) {
                for (var p in settings) {
                    if (!hasOwn.call(settings, p))
                        continue;
                    var val = settings[p];
                    if (typeof kernel.plugin[p] === "function") {
                        kernel.plugin[p](val);
                    } else {
                        kernel[p] = val;
                    }
                }
                return this;
            }
      require.config({
                alias: {
                    "jquery": {
                        src: path + "mass/demo/jquery-1.9.1.min.js",
                        deps: [],//没有依赖可以不写
                        exports: "jQuery" //要从全局作用域抽取的数据
                    }
                }
            });

    源码传递给config一个属性名为alias的对象集合,然后通过config遍历这个集合,过滤其中的属性(不是该对象的原生属性(也就是通过原型链添加的属性)),然后判断当前遍历到的属性是否是kernel对象的插件(这里用函数表示),如果是吊用该插件,然后通过当前的属性,拿到对应对象的值,将值作为参数传递给该插件。

    这里的alias是kernel的一个插件,下面是他的源码:

        kernel.plugin["alias"] = function(val) {
            var map = kernel.alias;
            for (var c in val) {
                if (hasOwn.call(val, c)) {
                    var prevValue = map[c];
                    var currValue = val[c];
                    if (prevValue) {
                        $.error("注意" + c + "出经重写过");
                    }
                    map[c] = currValue;
                }
            }
        };

    这个函数也就是上面所说的alias插件,该函数通过维护一个alias集合来保存所有需要加载的文件的别名和对应的js路径

    1、首先拿到所有的alias(别名),这里注意:

    var all = "mass,lang,class,flow,data,support,query,node,attr,css,event,ajax,fx";
    all.replace($.rword, function(a) {
            $.config.alias["$" + a] = basepath + a + ".js";
    });

    mass事先把属于自身框架的所有js文件都放到了这个集合当中去了。

    2、遍历传入的参数,做一些常规判断,如果命名相同,则进行重写操作,并进行提醒,不相同直接加入到alias集合中去

    加下来看require方法了:

       require("jquery", function($) {
                alert($)
                alert($("body").length);
                alert("回调调起成功");
                alert($("body").length) //这里不用domReady了
            })

    上面的代码传递给reqiire方法一个"jquery"和一个回调函数参数,下面来分析require方法的源码:

        window.require = $.require = function(list, factory, parent) {
            // 用于检测它的依赖是否都为2
            var deps = {},
                    // 用于保存依赖模块的返回值
                    args = [],
                    // 需要安装的模块数
                    dn = 0,
                    // 已安装完的模块数
                    cn = 0,
                    id = parent || "callback" + setTimeout("1");
            parent = parent || basepath;
            String(list).replace($.rword, function(el) {
                var url = loadJSCSS(el, parent)
                if (url) {
                    dn++;
                    if (modules[url] && modules[url].state === 2) {
                        cn++;
                    }
                    if (!deps[url]) {
                        args.push(url);
                        deps[url] = "司徒正美"; //去重
                    }
                }
            });
            modules[id] = {//创建一个对象,记录模块的加载情况与其他信息
                id: id,
                factory: factory,
                deps: deps,
                args: args,
                state: 1
            };
            if (dn === cn) { //如果需要安装的等于已安装好的
                fireFactory(id, args, factory); //安装到框架中
            } else {
                //放到检测列队中,等待checkDeps处理
                loadings.unshift(id);
            }
            checkDeps();
        };

    1、require方法接收三个参数:

    (1)、第一个list,如果通过config配置过别名和路径的话,那么这个list就是别名列表,如果不是的话,LoadJSCSS方法会做进一步的处理,下面会介绍LoadJSCSS方法。

    (2)、都二个factory,这个参数是回调函数

    (3)、第三个parent,可以通过这个参数指定basePath,basePath下面也会介绍

    2、

  • 相关阅读:
    eclipse如何卸载adt插件
    Android中的Toast.LENGTH_SHORT
    Frogger
    - Oil Deposits 深搜,就是所谓的dfs
    Aggressive cows
    Phone List
    Word Amalgamation
    Street Numbers
    Charm Bracelet——背包问题
    函数参考
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6472597.html
Copyright © 2020-2023  润新知