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 相关文章推荐
使用TextRange获取输入框中光标的位置的代码
Mar 08 Javascript
Jquery 基础学习笔记之文档处理
May 29 Javascript
js 替换功能函数,用正则表达式解决,js的全部替换
Dec 08 Javascript
Jquery实现视频播放页面的关灯开灯效果
May 27 Javascript
jquery对dom的操作常用方法整理
Jun 25 Javascript
jQuery点击按钮弹出遮罩层且内容居中特效
Dec 14 Javascript
一个可复用的vue分页组件
May 15 Javascript
在vue中使用jointjs的方法
Mar 24 Javascript
如何解决js函数防抖、节流出现的问题
Jun 17 Javascript
JS中超越现实的匿名函数用法实例分析
Jun 21 Javascript
js实现单元格拖拽效果
Feb 10 Javascript
微信小程序动态评分展示/五角星展示/半颗星展示/自定义长度展示功能的实现
Jul 22 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生成WAP页面
2006/10/09 PHP
PHP单态模式简单用法示例
2016/11/16 PHP
laravel框架实现为 Blade 模板引擎添加新文件扩展名操作示例
2020/01/25 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
JQuery与Ajax常用代码实现对比
2009/10/03 Javascript
禁止js文件缓存的代码
2010/04/09 Javascript
Javascript Function对象扩展之延时执行函数
2010/07/06 Javascript
JS按位非(~)运算符与~~运算符的理解分析
2011/07/31 Javascript
javascript中打印当前的时间实现思路及代码
2013/12/18 Javascript
原生js事件的添加和删除的封装
2014/07/01 Javascript
一个支付页面DEMO附截图
2014/07/22 Javascript
Javascript+CSS实现影像卷帘效果思路及代码
2014/10/20 Javascript
JavaScript中Math对象的方法介绍
2017/01/05 Javascript
BootStrap模态框不垂直居中的解决方法
2017/10/19 Javascript
vue+axios新手实践实现登陆的示例代码
2018/06/06 Javascript
微信小程序实现左侧滑动导航栏
2020/04/08 Javascript
js前端如何写一个精确的倒计时代码
2019/10/25 Javascript
TypeScript 运行时类型检查补充工具
2020/09/28 Javascript
在elementui中Notification组件添加点击事件实例
2020/11/11 Javascript
python获取文件扩展名的方法
2015/07/06 Python
Python selenium 父子、兄弟、相邻节点定位方式详解
2016/09/15 Python
Python实现批量读取图片并存入mongodb数据库的方法示例
2018/04/02 Python
python得到windows自启动列表的方法
2018/10/14 Python
python遍历小写英文字母的方法
2019/01/02 Python
python实现控制台输出彩色字体
2020/04/05 Python
Python logging模块异步线程写日志实现过程解析
2020/06/30 Python
python文件排序的方法总结
2020/09/13 Python
365 Tickets英国:全球景点门票
2019/07/06 全球购物
Aquatalia官网:意大利著名鞋履品牌
2019/09/26 全球购物
社会实践自我鉴定
2013/11/07 职场文书
妇女干部培训方案
2014/05/12 职场文书
应届生求职信
2014/05/31 职场文书
教师党员先进性教育自我剖析材料思想汇报
2014/09/24 职场文书
学校中秋节活动总结
2015/03/23 职场文书
2016年幼儿园庆六一开幕词
2016/03/04 职场文书
MySQL自定义函数及触发器
2022/08/05 MySQL