建立AMD、CMD、nodeJS通用的模板引擎,并封装发布到npm,方便使用

首先我们先来写一个简单的模板引擎代码
var str = "My name is {{name}},I'm {{age}} years old";

var regex = /{{([a-zA-Z_$][0-9a-zA-Z\._$]*)}}/g;

 //match 匹配的字串
 //key 匹配正则括号中的值(如有多个括号就会有多个值)
 //offset 匹配字串的偏移量
 //string 整个字符串

  var data = {
  name: 'jimmy',
  age: 25,
  sex: '男',
  friend: {
    name: 'tom'
  }
};

var tpl = str.replace(regex, function(match, key, offset, string){
  return data[key] || match;
});

console.log(tpl);//"My name is jimmy,I'm 25 years old"

优化简单的模板引擎代码

上面的代码有缺陷,如果在对象中有嵌套层的话,那么是无法被上面的正则匹配替换的。

将上述代码{{name}}修改成{{friend.name}}则不替换:

var str = "My {{friend.name}} is jimmy,I'm {{age}} years old";
console.log(tpl);//"My {{friend.name}} is jimmy,I‘m 25 years old"

现在我们来修改下代码:

//match 匹配的字串
//key 匹配正则括号中的值
//offset 匹配字串的偏移量
//string 整个字符串
var a = str.replace(regex, function(match, key, offset, string){
  var keys = key.split('.'),
      obj = data;
  while(keys.length > 0) {
    key = keys.shift();
    obj = obj[key];
  }
  return obj || match;
});

console.log(a);//"My name is tom,I'm 25 years old";

我们将{{friend.name}} 中的friend.name 通过 split('.') 截取成数组形成["friend", "name"],并且通过判断长度length,循环调出最里面的值,直到循环到最里层,取到想要的值
相当于:

//第一次循环:
 obj = obj[key];//{name:"tom"}
//第二次循环:
 obj = obj[key];//tom

那么现在来写成函数
function easyTpl(data, str) {
  var regex = /{{([a-zA-Z_$][0-9a-zA-Z\._$]*)}}/g;
  var result = str.replace(regex, function(match, key, offset, string) {
    var keys = key.split('.'),
      obj = data;
    while (keys.length > 0) {
      key = keys.shift();
      obj = obj[key];
    }
    return obj || match;
  });
  return result;
}

var tpl = easyTpl(data, str);
console.log(tpl);

准备封装

首先封装的代码不仅要起到隔离作用域的作用,并且要能够在CMD、AMD、nodejs中通用使用,也就是说将这段封装好的代码移到各自环境中,自己匹配适合的代码生成模块。

我们先来定义一个自执行函数

(function(name, definition, context){
  //TODO::
})(name, function(){}, this);

自执行函数将要接受 一个(定义的函数名,函数,作用域)

那么我们一步一步添加

(function(name, definition, context){
  if(typeof module != 'undefined' && module.exports){
    //在 node 环境中
    module.exports = definition();
  } else if (typeof context['define'] == 'function' && (context['define']['amd']) || typeof context['define'] == 'function' && (context['define']['cmd'])) {
    //在 AMD(requirejs) 或者 在 CMD(seajs) 环境中 
    define(definition);
  } else{
    //在客户端client中 
    context[name] = definition();
  }
})(name, function(){}, this);

在这段代码中,
第一个if判断语句
通过能力检测判断 module ,module是在node环境中才有的方法,并且module.exports存在,在将函数definition放进mudule.exports 环境中,成为node环境下的代码。
第二个判断语句
通过能力检测判断context['define']['amd']或context['define']['cmd']并且都判断context是一个函数,这样说明在CMD或者AMD环境下,他们的定义磨矿化函数的方式都是difine(),所以通用格式写成 difine(definition)。

最后一个是在不是 nodejs 和 CMD AMD 环境下 ,默认在客户端window环境下,所以context 等于 window 。在window全局作用域下添加变量名name,并放入definition函数


完整代码可以写成
(function(name, definition, context) {
  if (typeof module != 'undefined' && module.exports) {
    //在 node 环境中
    module.exports = definition();
  } else if (typeof context['define'] == 'function' && (context['define']['amd']) || typeof context['define'] == 'function' && (context['define']['cmd'])) {
    //在 AMD(requirejs) 或者 在 CMD(seajs) 环境中 
    define(definition);
  } else {
    //在客户端中 client
    context[name] = definition();
  }
})('easyTpl', function() {
  return function(data, str) {
    var regex = /{{([a-zA-Z_$][0-9a-zA-Z\._$]*)}}/g;
    return str.replace(regex, function(match, key, offset, string) {
      var keys = key.split('.'),
        obj = data;
      while (keys.length > 0) {
        obj = obj[keys.shift()];
      }
      return obj || match;
    });
  }
}, this);

最后 命令行操作
通过 npm init 生成packge.json
npm login
npm publish 发布上线
并通过 npm官网查找
下次自己使用通过 npm intall xxx 即可下载安装到 全局或者 当前文件夹的 node_modules中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容