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 相关文章推荐
IE7中javascript操作CheckBox的checked=true不打勾的解决方法
Dec 07 Javascript
需要做特殊处理的DOM元素属性的访问
Nov 05 Javascript
checkbox设置复选框的只读效果不让用户勾选
Aug 12 Javascript
在JavaScript中实现类的方式探讨
Aug 28 Javascript
java必学必会之static关键字
Dec 03 Javascript
图解js图片轮播效果
Dec 20 Javascript
javascript仿百度输入框提示自动下拉补全
Jan 07 Javascript
jQuery插件imgPreviewQs实现上传图片预览
Jan 15 Javascript
javascript小数精度丢失的完美解决方法
May 31 Javascript
通过示例彻底搞懂js闭包
Aug 10 Javascript
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
Feb 19 Javascript
vue实现简单瀑布流布局
May 28 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模板类代码
2008/09/07 PHP
如何使用PHP给图片加水印
2016/10/12 PHP
php使用gd2绘制基本图形示例(直线、圆、正方形)
2017/02/15 PHP
封装的jquery翻页滚动(示例代码)
2013/11/18 Javascript
JS cookie中文乱码解决方法
2014/01/28 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
jQuery AJAX timeout 超时问题详解
2016/06/21 Javascript
JavaScript动态检验密码强度的实现方法
2016/11/09 Javascript
jQuery实现的弹幕效果完整实例
2017/09/06 jQuery
Angular2使用vscode断点调试ts文件的方法
2017/12/13 Javascript
详解使用vue-admin-template的优化历程
2018/05/20 Javascript
vue插件draggable实现拖拽移动图片顺序
2018/12/01 Javascript
使用FormData实现上传多个文件
2018/12/04 Javascript
JS使用JSON.parse(),JSON.stringify()实现对对象的深拷贝功能分析
2019/03/06 Javascript
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
2019/03/28 Javascript
基于javascript实现贪吃蛇经典小游戏
2020/04/10 Javascript
python实现模拟按键,自动翻页看u17漫画
2015/03/17 Python
python提取字典key列表的方法
2015/07/11 Python
python中matplotlib实现最小二乘法拟合的过程详解
2017/07/11 Python
python MySQLdb使用教程详解
2018/03/20 Python
python实现画一颗树和一片森林
2018/06/25 Python
python3.x+pyqt5实现主窗口状态栏里(嵌入)显示进度条功能
2019/07/04 Python
Pyorch之numpy与torch之间相互转换方式
2019/12/31 Python
关于tf.matmul() 和tf.multiply() 的区别说明
2020/06/18 Python
美国当红的名品折扣网:Gilt Groupe
2016/08/15 全球购物
SQL语言面试题
2013/08/27 面试题
经理秘书岗位职责
2013/11/14 职场文书
主治医师岗位职责
2013/12/10 职场文书
房屋改造计划书
2014/01/10 职场文书
公司薪酬管理制度
2014/01/31 职场文书
市场部管理制度
2014/02/02 职场文书
三方协议书
2015/01/27 职场文书
武夷山导游词
2015/02/03 职场文书
学校运动会加油词
2015/07/18 职场文书
alibaba seata服务端具体实现
2022/02/24 Java/Android
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis