美文网首页
建立AMD、CMD、nodeJS通用的模板引擎,并封装发布到np

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

作者: 李大嘴JimmyLee | 来源:发表于2016-10-12 20:07 被阅读0次
    首先我们先来写一个简单的模板引擎代码
    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中。

    相关文章

      网友评论

          本文标题:建立AMD、CMD、nodeJS通用的模板引擎,并封装发布到np

          本文链接:https://www.haomeiwen.com/subject/emwiyttx.html