javascript 构建模块化开发过程解析


Posted in Javascript onSeptember 11, 2019

在使用 sea.js 、require.js 、 angular 的时候。

我们使用到 define 、 module(require) 的方式,定义模块,和依赖模块

下面给出 define 和 module 的简单实现。 其本质,就是往一个对象上面添加方法

var F = {};
F.define = function(str,fn){
  var parts = str.split(".");
  var parent = this; // parent 当前模块的父模块
  var i = len = 0;
  //如果第一个模块是模块单体对象,则移除
  if(parts[0] == "F"){
    parts = parts.slice(1);
  }
   
  //屏蔽对 define module 模块方法重写
  if(parts[0] == "define" || parts[0] == "module"){
    return ;
  }     
   
  for(len = parts.length; i < len-1; i++){
    //如果父模块中不存在当前模块
    if(typeof parent[parts[i]] === 'undefined'){
      //声明当前模块
      parent[parts[i]] = {};
    }
    //缓存下一层父模块
    parent = parent[parts[i]];
  }
   
  if(fn && parts[i]){
    //如果给定模块方法,则绑定该模块的方法,
    parent[parts[i]] = fn();
  }
  return this;
}
 
F.module = function(){
  var args = [].slice.call(arguments);//复制参数
  var fn = args.pop(); //获取回调
   
  var parts = args[0] && args[0] instanceof Array ? args[0] : args;
   
  //模块的依赖
  var modules = [];
   
  //模块的路由
  var modIDs = "";
   
  //依赖模块的索引
  var i = 0;
   
  var len = parts.length; // 依赖模块的长度
   
  var parent,j,jlen; //父级模块,模块路由层级索引,模块路由层级长度
   
  while(i < len){
    if(typeof parts[i] == "string"){
      parent = this;
      //解析路由,并且屏蔽掉 F
      modIDs = parts[i].replace(/^F\./,"").split(".");
      //遍历模块层级
      for( j = 0,jlen = modIDs.length; j < jlen; j++){
        //迭代 父模块
        parent = parent[modIDs[j]] || false;
      }
      modules.push(parent); //将模块添加到依赖列表
    }else{
      //直接将模块添加到依赖列表
      modules.push(parts[i]);
    }
    //取下一个模块
    i++;
  }
   
   
  //执行回调,将依赖的模块注入
  fn.apply(null,modules);  
} 
//定义 string 模块
F.define("string",function(){
  return {
    trim(str){
      return str.replace(/^s+|\s+$/g,"");
    }
  }
});
//定义 string 模块,的子模块 sub
F.define("string.sub",function(){
  return {
    low(str){
      return str.toLowerCase();
    }
  }
});
console.log(F);
//使用模块
F.module(["string","string.sub",document],function(str,strSub,doc){
  console.log(str,strSub,doc)
});

当然了,这里使用的,F 对象,实际应用中,应该写在闭包里面。不能让外界直接访问,于是有如下代码。

var Sea = (function(){
  var F = {};
    F.define = function(str,fn){
    var parts = str.split(".");
    var parent = this; // parent 当前模块的父模块
    var i = len = 0;
     
    //如果第一个模块是模块单体对象,则移除
    if(parts[0] == "F"){
      parts = parts.slice(1);
    }
     
    //屏蔽对 define module 模块方法重写
    if(parts[0] == "define" || parts[0] == "module"){
      return ;
    }     
     
    for(len = parts.length; i < len-1; i++){
      //如果父模块中不存在当前模块
      if(typeof parent[parts[i]] === 'undefined'){
        //声明当前模块
        parent[parts[i]] = {};
      }
      //缓存下一层父模块
      parent = parent[parts[i]];
    }
     
    if(fn && parts[i]){
      //如果给定模块方法,则绑定该模块的方法,
      parent[parts[i]] = fn();
    }
    return this;
  }
   
  F.module = function(){
    var args = [].slice.call(arguments);//复制参数
    var fn = args.pop(); //获取回调
     
    var parts = args[0] && args[0] instanceof Array ? args[0] : args;
     
    //模块的依赖
    var modules = [];
     
    //模块的路由
    var modIDs = "";
     
    //依赖模块的索引
    var i = 0;
     
    var len = parts.length; // 依赖模块的长度
     
    var parent,j,jlen; //父级模块,模块路由层级索引,模块路由层级长度
     
    while(i < len){
      if(typeof parts[i] == "string"){
        parent = this;
        //解析路由,并且屏蔽掉 F
        modIDs = parts[i].replace(/^F\./,"").split(".");
        //遍历模块层级
        for( j = 0,jlen = modIDs.length; j < jlen; j++){
          //迭代 父模块
          parent = parent[modIDs[j]] || false;
        }
        modules.push(parent); //将模块添加到依赖列表
      }else{
        //直接将模块添加到依赖列表
        modules.push(parts[i]);
      }
      //取下一个模块
      i++;
    }
     
     
    //执行回调,将依赖的模块注入
    fn.apply(null,modules);
  }
  return {
    define:function(){
      F.define.apply(F,arguments);
    },
    module:function(){
      F.module.apply(F,arguments);
    }
  }
})();
 
 
//定义 string 模块
Sea.define("string",function(){
  return {
    trim(str){
      return str.replace(/^s+|\s+$/g,"");
    }
  }
});
//定义 string 模块,的子模块 sub
Sea.define("string.sub",function(){
  return {
    low(str){
      return str.toLowerCase();
    }
  }
});
console.log(Sea);
//使用模块
Sea.module(["string","string.sub",document],function(str,strSub,doc){
  console.log(str,strSub,doc)
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery插件 cluetip 关键词注释
Jan 12 Javascript
(function($){...})(jQuery)的意思
Jul 22 Javascript
javascript每日必学之多态
Feb 23 Javascript
javascript正则表达式之分组概念与用法实例
Jun 16 Javascript
多种方式实现js图片预览
Dec 12 Javascript
利用vue开发一个所谓的数独方法实例
Dec 21 Javascript
Vue 组件传值几种常用方法【总结】
May 28 Javascript
vue实现element-ui对话框可拖拽功能
Aug 17 Javascript
vue中使用props传值的方法
May 08 Javascript
史上最为详细的javascript继承(推荐)
May 18 Javascript
layer.prompt输入层的例子
Sep 24 Javascript
vue 强制组件重新渲染(重置)的两种方案
Oct 29 Javascript
解决layer弹出层msg的文字不显示的问题
Sep 11 #Javascript
js贪心算法 钱币找零问题代码实例
Sep 11 #Javascript
解决layui使用layui-icon出现默认图标的问题
Sep 11 #Javascript
js图数据结构处理 迪杰斯特拉算法代码实例
Sep 11 #Javascript
js简单的分页器插件代码实例
Sep 11 #Javascript
解决在layer.open中使用时间控件laydate失败的问题
Sep 11 #Javascript
关于ckeditor在bootstrap中modal中弹框无法输入的解决方法
Sep 11 #Javascript
You might like
PHP后台微信支付和支付宝支付开发
2017/04/28 PHP
PHP微信H5支付开发实例
2018/07/25 PHP
PHP使用JpGraph绘制折线图操作示例【附源码下载】
2019/10/18 PHP
用javascript动态调整iframe高度的方法
2007/03/06 Javascript
基于jquery的防止大图片撑破页面的实现代码(立即缩放)
2011/10/24 Javascript
解析Jquery取得iframe中元素的几种方法
2013/07/04 Javascript
js获取对象为null的解决方法
2013/11/21 Javascript
Javascript Ajax异步读取RSS文档具体实现
2013/12/12 Javascript
javascript中数组的冒泡排序使用示例
2013/12/18 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
jQuery实现回车键(Enter)切换文本框焦点的代码实例
2014/05/05 Javascript
jQuery和AngularJS的区别浅析
2015/01/29 Javascript
JS动态修改表格cellPadding和cellSpacing的方法
2015/03/31 Javascript
bootstrap中使用google prettify让代码高亮的方法
2016/10/21 Javascript
扩展Bootstrap Tooltip插件使其可交互的方法
2016/11/07 Javascript
jquery 校验中国身份证号码实例详解
2017/04/11 jQuery
JS点击图片弹出文件选择框并覆盖原图功能的实现代码
2017/08/25 Javascript
谈谈JS中的!!
2017/12/07 Javascript
在vue项目中引入highcharts图表的方法(详解)
2018/03/05 Javascript
jquery实现选项卡切换代码实例
2019/05/14 jQuery
Echarts实现多条折线可拖拽效果
2019/12/19 Javascript
Python实现的下载网页源码功能示例
2017/06/13 Python
python利用urllib和urllib2访问http的GET/POST详解
2017/09/27 Python
Django使用HttpResponse返回图片并显示的方法
2018/05/22 Python
对pandas中时间窗函数rolling的使用详解
2018/11/28 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
2019/06/18 Python
基于Python实现人脸自动戴口罩系统
2020/02/06 Python
播音主持女孩的自我评价分享
2013/11/20 职场文书
服务行业个人求职的自我评价
2013/12/12 职场文书
医药个人求职信范文
2014/01/29 职场文书
横幅标语大全
2014/06/17 职场文书
大学毕业生管理学求职信
2014/09/01 职场文书
我的大学四年规划书范文2014
2014/09/26 职场文书
2015年员工工作总结范文
2015/04/08 职场文书
优秀大学生申请书
2019/06/24 职场文书
Python时间操作之pytz模块使用详解
2022/06/14 Python