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 相关文章推荐
浅析javascript的return语句
Dec 15 Javascript
更高效的使用JQuery 这里总结了8个小技巧
Apr 13 Javascript
Function.prototype.apply()与Function.prototype.call()小结
Apr 27 Javascript
基于Marquee.js插件实现的跑马灯效果示例
Jan 25 Javascript
浅谈Angular HttpClient简单入门
May 04 Javascript
JS非行间样式获取函数的实例代码
Jun 05 Javascript
vue实现局部刷新的实现示例
Apr 16 Javascript
webpack-mvc 传统多页面组件化开发详解
May 07 Javascript
15 分钟掌握vue-next响应式原理
Oct 13 Javascript
javascript开发实现贪吃蛇游戏
Jul 31 Javascript
Vue.js原理分析之nextTick实现详解
Sep 07 Javascript
解决vue elementUI 使用el-select 时 change事件的触发问题
Nov 17 Vue.js
解决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/04/25 PHP
php四种基础算法代码实例
2013/10/29 PHP
PHP面相对象中的重载与重写
2017/02/13 PHP
js使用split函数按照多个字符对字符串进行分割的方法
2015/03/20 Javascript
jQuery的animate函数实现图文切换动画效果
2015/05/03 Javascript
AngularJS基础学习笔记之指令
2015/05/10 Javascript
用jQuery获取table中行id和td值的实现代码
2016/05/19 Javascript
Bootstrap3.0建站教程(一)之bootstrap表单元素排版
2016/06/01 Javascript
利用Vue.js指令实现全选功能
2016/09/08 Javascript
AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】
2016/12/13 Javascript
js遍历json对象所有key及根据动态key获取值的方法(必看)
2017/03/09 Javascript
解决vue中对象属性改变视图不更新的问题
2018/02/23 Javascript
使用validate.js实现表单数据提交前的验证方法
2018/09/04 Javascript
JS重学系列之聊聊new操作符
2019/03/04 Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
2020/08/14 Javascript
[34:41]夜魇凡尔赛茶话会 第二期02:你画我猜
2021/03/11 DOTA
python通过post提交数据的方法
2015/05/06 Python
python通过apply使用元祖和列表调用函数实例
2015/05/26 Python
python读取文本中数据并转化为DataFrame的实例
2018/04/10 Python
tensorflow实现简单的卷积网络
2018/05/24 Python
Django 忘记管理员或忘记管理员密码 重设登录密码的方法
2018/05/30 Python
python使用matplotlib绘制热图
2018/11/07 Python
pandas DataFrame 交集并集补集的实现
2019/06/24 Python
Python如何转换字符串大小写
2020/06/04 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
CSS3 开发工具收集
2010/04/17 HTML / CSS
JD Sports瑞典:英国领先的运动时尚商店
2018/01/28 全球购物
工地宣传标语
2014/06/18 职场文书
公司活动总结范文
2014/07/01 职场文书
纪念9.18事变演讲稿
2014/09/14 职场文书
商铺门面租房协议书
2014/10/21 职场文书
2016年大学生暑期社会实践方案
2015/11/26 职场文书
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
2022/02/12 Redis
避坑之 JavaScript 中的toFixed()和正则表达式
2022/04/19 Javascript
python使用pycharm安装pyqt5以及相关配置
2022/04/22 Python
Android开发手册TextInputLayout样式使用示例
2022/06/10 Java/Android