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 相关文章推荐
使用js实现一个可编辑的select下拉列表
Feb 20 Javascript
jQuery中slideUp()方法用法分析
Dec 24 Javascript
浅谈JavaScript中的String对象常用方法
Feb 25 Javascript
JavaScript函数内部属性和函数方法实例详解
Mar 17 Javascript
javascript断点调试心得分享
Apr 23 Javascript
jQuery验证插件validate使用详解
May 11 Javascript
angular.fromJson与toJson方法用法示例
May 17 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
May 09 jQuery
原生JS实现汇率转换功能代码实例
May 13 Javascript
jQuery 选择器用法实例分析【prev + next】
May 22 jQuery
js实现验证码功能
Jul 24 Javascript
Nuxt.js nuxt-link与router-link的区别说明
Nov 06 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中多维数组按指定value排序的实现代码
2014/08/19 PHP
PHP面向对象程序设计实例分析
2016/01/26 PHP
Yii2.0框架实现带分页的多条件搜索功能示例
2019/02/20 PHP
详解PHP 二维数组排序保持键名不变
2019/03/06 PHP
一文掌握PHP Xdebug 本地与远程调试(小结)
2019/04/23 PHP
Laravel6.18.19如何优雅的切换发件账户
2020/06/14 PHP
用tip解决Ext列宽度不够的问题
2008/12/13 Javascript
一个收集图片的bookmarlet(js 刷新页面中的图片)
2010/05/27 Javascript
jQuery学习笔记(4)--Jquery中获取table中某列值的具体思路
2013/04/10 Javascript
jquery点击页面任何区域实现鼠标焦点十字效果
2013/06/21 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
基于cssSlidy.js插件实现响应式手机图片轮播效果
2016/08/30 Javascript
轻松掌握JavaScript状态模式
2016/09/07 Javascript
详解JS对象封装的常用方式
2016/12/30 Javascript
微信{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]"}
2018/10/12 Javascript
vue实现微信分享功能
2018/11/28 Javascript
JavaScript 防盗链的原理以及破解方法
2020/12/29 Javascript
[42:32]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第二局
2016/02/27 DOTA
Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
2008/09/06 Python
python通过ElementTree操作XML获取结点读取属性美化XML
2013/12/02 Python
Python中编写ORM框架的入门指引
2015/04/29 Python
python使用pil进行图像处理(等比例压缩、裁剪)实例代码
2017/12/11 Python
浅谈Python中eval的强大与危害
2019/03/13 Python
在django模板中实现超链接配置
2019/08/21 Python
Python如何使用input函数获取输入
2020/08/06 Python
美国高街时尚品牌:OASAP
2016/07/24 全球购物
Viking Direct荷兰:购买办公用品
2019/06/20 全球购物
物业门卫岗位职责
2013/12/28 职场文书
学习保证书范文
2014/04/30 职场文书
2014年志愿者工作总结
2014/11/20 职场文书
2015教师节通讯稿
2015/07/20 职场文书
《静夜思》教学反思
2016/02/17 职场文书
go类型转换及与C的类型转换方式
2021/05/05 Golang
深入浅出的讲解:信号调制到底是如何实现的
2022/02/18 无线电
JavaScript获取URL参数的方法分享
2022/04/07 Javascript
Redis基本数据类型Set常用操作命令
2022/06/01 Redis