JS模板引擎 :ArtTemplate

本文详细介绍了如何实现一个简易的JS模板引擎,包括模板的定义、数据的注入、结果的生成等关键步骤,同时提供了核心代码实现及解析细节,帮助开发者理解模板引擎的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JS模板引擎 :ArtTemplate 

http://www.cnblogs.com/chen4342024/p/4916070.html

上一篇初略的介绍了一下javascript中的模板引擎,有兴趣的可以戳 这里  。

这一篇将带着大家一起做一个简易的模板引擎,

上一篇介绍到:模板引擎其实做的就是两件事。

  1. 根据一定的规则,解析我们所定义的模板
  2. 根据数据以及模板生成html(其实背后也是用的字符串拼接)

那么,首先,我们要有一个模板,一份数据,以及想生成的结果。

例如:模板:

复制代码
1 <script id="test" type="text/html">
2     <p><%=title%></p>
3     <p><%=msg%></p>
4     <ul>
5         <% for (var i = 0; i < list.length; i ++) { %>
6         <li><%= list[i] %></li>
7         <% } %>
8     </ul>
9 </script>
复制代码

数据:

复制代码
<script>
    var data = {
        title: '基本例子',
        msg: "这是一个例子",
        list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
    };
    var html = template('test', data);
    document.getElementById('content').innerHTML = html;
</script>
复制代码

结果:

现在,我们就来实现上面这个例子。

首先,我们需要定义我们的template方法。

复制代码
    var template = function (templateName, data) {
        return renderFile(templateName, data);
    };

    var renderFile = function (templateName, data) {
        var render = template.get(templateName);
        return render(data);
    };
复制代码

然后,获取我们缓存的template 的render方法

复制代码
template.get = function (templateName) {
        var cache;
        if (defaults.cache && cacheStore[templateName]) {
            cache = cacheStore[templateName];
        } else if (typeof document === 'object') {
            // 加载模板并编译
            var elem = document.getElementById(templateName);
            if (elem) {
                var source = elem.innerHTML;
                cache = compile(source);
                if (templateName && defaults.cache) {
                    cacheStore[templateName] = cache;
                }
            }
        }
        return cache;
 };
复制代码

上面的代码,相信大家也都看得懂,主要是对渲染方法进行缓存,以提升效率。接下来是其中最重要的编译方法。

复制代码
    var compile = template.compile = function (source, options) {
        var options = extend(options, defaults);
        var render = compiler(source, options);
        return render;
    };

    var compiler = function (source, options) {
        var openTag = options.openTag;
        var closeTag = options.closeTag;
        var cache = options.cache;

        //此处开始解析模板,并生成渲染函数
        var headerCode = "'use strict';" + "\n" + "var ";
        var mainCode = "$out='';";
        var footerCode = "return new String($out);";

        var uniq = {};

        //对模板中html代码的处理
        var html = function (code) {
            if (code) {
                code = "$out+=" + stringify(code) + ";" + "\n";
            }
            return code;
        };

        //对模板中逻辑部分的处理
        var logic = function (code) {
            // 输出语句. 编码: <%=value%> 不编码:<%=#value%>
            if (code.indexOf('=') === 0) {
                code = code.replace(/^=[=#]?|[\s;]*$/g, '');
                code = "$out+=" + code + ";";
            }
            // 提取模板中的变量名
            each(getVariable(code), function (name) {
                // name 值可能为空,在安卓低版本浏览器下
                if (!name || uniq[name]) {
                    return;
                }
                var value;
                // 声明模板变量
                value = "$data." + name;
                headerCode += name + "=" + value + ",";
                uniq[name] = true;

            });
            return code + "\n";
        };

        each(source.split(closeTag), function (code) {
            //此时代码已被截取成两部分,一部分是纯html,
            //一部分是逻辑代码,即是包含在html<%logic%>html里面的部分
            code = code.split(openTag);
            var htmlStr = code[0];

            var logicStr = code[1];

            mainCode += html(htmlStr);

            if (code.length > 1 && logicStr) {

                mainCode += logic(logicStr);
            }
        });




        var code = headerCode + mainCode + footerCode;
        try {
            var Render = new Function("$data", code);
            return Render;

        } catch (e) {
            e.temp = "function anonymous($data) {" + code + "}";
            throw e;
        }


    };
复制代码

这个方法,便是将模板引擎中的内容解析,并生成渲染方法。

生成之后的渲染方法大概是下面这个样子。

  View Code

模板引擎的解析细节:

大家知道,想生成上面的方法,无非就是通过evel 或者Funciton 之类的方法,将一个字符串生成成一个function。

这里采用的是  var Render = new Function("$data", code);来生成渲染方法。其中$data为参数,code为字符串。 Function方法的具体使用可以参考官方文档 点我

那么,我们想要生成这个Render方法,最重要的事便是 拼接 code 了。

拼接code时,headerCode 和 footerCode 是不变的,对任何模板都是一样的。所以重点工作在于中间的mainCode。

这里,mainCode主要分为两部分,一部分是模板中的html部分,一部分是模板中的逻辑部分(也就是包含在<%><%>里面的)

compiler通过分割<%>,将里面的逻辑部分和html部分分离出来,然后再分别处理。

  • html部分无需特殊处理,只需要拼接进mainCode就可以了。
  • logic部分,就需要特殊处理了。例如 例子中的title,这个值,我们需要判断是变量还是关键字(for if ..,这个稍后会讲如何提取),
    如果是变量,就必须先赋值:var title = $data.title,$data即为渲染方法的参数,也就是用户到时候会传进来的。
    然后再直接将title追加到 mainCode中去就可以了。

至于logic部分,如何提取变量主要是通过正则表达式来提取。

  View Code

这里,主要各个正则的用处都写了注释了。

主要做了:

  1. 过滤掉系统关键字,
  2. 过滤掉数字开头的变量(不合法变量)
  3. 由于1,2部,此时可能首尾有逗号,故,去除首尾的逗号
  4. 根据一个或多个逗号,分隔成参数数组   如:param1,param2,,param3=> ["param1","param2","param3"]

 

就这样,渲染方法就拼接完了。

最后,这里只是实现了js模板中简易的功能。后期诸如helper,include,还会在继续讲。

完整源码地址 : https://github.com/chen4342024/andyTemplate

如果有哪一方面讲的有问题。望不吝指教~

 

最后问个问题,电脑是win10系统,用什么博客编辑器比较好?官方推荐的window live writer 安装不了!!!

 

一艘船如果没有目标,那无论海面上哪个方向的风,都是逆风! 个人主页: http://chenblog.sinaapp.com/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值