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 相关文章推荐
关于取不到由location.href提交而来的上级页面地址的解决办法
Jul 30 Javascript
Javascript String.replace的妙用
Sep 08 Javascript
Javascript this 的一些学习总结
Aug 02 Javascript
JQuery设置文本框和密码框得到焦点时的样式
Aug 30 Javascript
Jquery左右滑动插件之实现超级炫酷动画效果附源码下载
Dec 02 Javascript
for循环 + setTimeout 结合一些示例(前端面试题)
Aug 30 Javascript
解决ie img标签内存泄漏的问题
Oct 13 Javascript
代码详解Vuejs响应式原理
Dec 20 Javascript
JS与CSS3实现图片响应鼠标移动放大效果示例
May 04 Javascript
微信小程序自定义select下拉选项框组件的实现代码
Aug 28 Javascript
jquery实现进度条状态展示
Mar 26 jQuery
JS中FileReader类实现文件上传及时预览功能
Mar 27 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
模拟OICQ的实现思路和核心程序(一)
2006/10/09 PHP
web目录下不应该存在多余的程序(安全考虑)
2012/05/09 PHP
PHP 冒泡排序 二分查找 顺序查找 二维数组排序算法函数的详解
2013/06/25 PHP
又拍云异步上传实例教程详解
2016/04/19 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
2019/03/12 PHP
JS Array对象入门分析
2008/10/30 Javascript
jQuery 源码分析笔记(5) jQuery.support
2011/06/19 Javascript
再谈querySelector和querySelectorAll的区别与联系
2012/04/20 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
2013/08/02 Javascript
Javascript基础知识(三)BOM,DOM总结
2014/09/29 Javascript
node.js中的path.resolve方法使用说明
2014/12/08 Javascript
JS控制网页动态生成任意行列数表格的方法
2015/03/09 Javascript
javascript引用类型指针的工作方式
2015/04/13 Javascript
JS控制静态页面传递参数并获取参数应用
2016/08/10 Javascript
微信小程序 122100版本更新问题解决方案
2016/12/22 Javascript
Bootstrap导航中表单简单实现代码
2017/03/06 Javascript
vue 过滤器filter实例详解
2018/03/14 Javascript
vue模式history下在iis中配置流程
2019/04/17 Javascript
node命令行工具之实现项目工程自动初始化的标准流程
2019/08/12 Javascript
详解Vue的组件中data选项为什么必须是函数
2020/08/17 Javascript
python3.0 字典key排序
2008/12/24 Python
浅谈python 线程池threadpool之实现
2017/11/17 Python
python绘制简单彩虹图
2018/11/19 Python
pymongo中聚合查询的使用方法
2019/03/22 Python
Django项目中添加ldap登陆认证功能的实现
2019/04/04 Python
详解python3中用HTMLTestRunner.py报ImportError: No module named 'StringIO'如何解决
2019/08/27 Python
给Django Admin添加验证码和多次登录尝试限制的实现
2020/07/26 Python
大唐面试试题(CPU,UNIX等等)
2012/01/11 面试题
工厂厂长的职责
2013/12/12 职场文书
八项规定整改方案
2014/10/01 职场文书
计划生育证明格式及范本
2014/10/09 职场文书
实习工作表现评语
2014/12/31 职场文书
学会感恩主题班会
2015/08/12 职场文书
会计专业自荐信范文
2019/05/22 职场文书
Vue Element UI自定义描述列表组件
2021/05/18 Vue.js
解决Navicat for MySQL 连接 MySQL 报2005错误的问题
2021/05/29 MySQL