javascript 模板系统

由于各种原因,被逼使用前台模板。看了一下其他JS模板库的实现,发现其原理并不难,遂决定重造轮子。使用ROR.erb风格。换言之,逻辑是写在"<%"与"%>"之间,如果是注释,则用"<%#"与"%>",凡是后台传过来的变量都加上@来标记。现在这个模板系统还没有搭载任何helper方法,也不依赖任何代码,因此非常精短。

<!doctype html>
<html>
    <head>
        <title>postMessage by 司徒正美</title>
        <meta charset="utf-8"/>
        <meta content="IE=8" http-equiv="X-UA-Compatible"/>
        <meta name="keywords" content="javascript模板 by 司徒正美" />
        <meta name="description" content="javascript模板 by 司徒正美" />
        <title>javascript模板 by 司徒正美</title>
    </head>
    <body>
        <h1>javascript模板 by 司徒正美</h1>
        <textarea id="tmpl" style="display:none;" >
        <h2><%= @name %></h2>
        <%# 这是注释 %>
        <ul>
        <% for(var i=0; i<@supplies.length; i++) {%>
            <li><%= @supplies[i] %></li>
        <% } %>
        </ul>
        <p style="text-indent:2em;"><%=@address %></p>
        </textarea>
        <script src="http://files.cnblogs.com/rubylouvre/tmpl.js"></script>
        <script>
            window.onload = function(){
                dom.erb("tmpl", {name:"司徒正美",supplies:["第一个LI元素","第二个LI元素","第三个LI元素","第四个LI元素"],address:"异次元"})
            }
        </script>
    </body>
</html>

模板系统:


 //司徒正美 javascript template - http://www.cnblogs.com/rubylouvre/ - MIT Licensed
(function () {

    var metaObject = { 
        '/b': '//b',
        '/t': '//t',
        '/n': '//n',
        '/f': '//f',
        '/r': '//r',
        '//': ''
    };

    var dom = {
        quote: function (str) {
            str = str.replace(/[/x00-/x1f//]/g, function (chr) {
                var special = metaObject[chr];
                return special ? special : '//u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)
            });
            return '"' + str.replace(/"/g, '//"') + '"';
        }
    };
//selector ,必须,String, 模板容器textarea的ID值
//json,必须,对象字面量或JSON
//onsite,可选,Boolean,是否就地替换掉模板容器,默认true,如果为false,则返回一个文档碎片,交由用户自己插入到需要的地方
    dom.erb = function (selector, json, onsite) {
        onsite = !!onsite|| true;
        var el = document.getElementById(selector);
        if (!el) throw "找不到目标元素";
        var text = el.value,
            erb = dom.erb;
        if (!erb[selector]) {
            var arr = text.split(//s*<%/s*|/s*%>/s*/g),
                buff = ["var __views = [];/n"]
                for (var i = 0, segment, n = arr.length; i < n; i++) {
                    segment = arr[i]
                    if (i & 1) { //偶数项,处理动态的逻辑
                        switch (segment.charAt(0)) {
                        case "#":
                            //处理注释
                            buff.push(erb.startOfHTML, dom.quote("<!--" + segment + "-->"), erb.endOfHTML);
                            break;
                        case "=":
                            if (segment.indexOf("@") !== -1) { //处理后台返回的变量(输出到页面的)
                                buff.push(erb.startOfHTML, segment.slice(1).replace(erb.rAt, "$1json."), erb.endOfHTML);
                            } else {
                                buff.push(erb.startOfHTML, segment.slice(1), erb.endOfHTML)
                            }
                            break;
                        default:
                            if (segment.indexOf("@") !== -1) { //处理后台返回的变量
                                buff.push(segment.replace(erb.rAt,  "$1json."), "/n");
                            } else {
                                buff.push(segment, "/n")
                            }
                            break;
                        }
                    } else { //奇数项,处理静态的HTML片断
                        buff.push(erb.startOfHTML, dom.quote(segment), erb.endOfHTML);
                    }
                }
                erb[selector] = new Function("json", buff.join("") + ';return __views.join("");')
        }
        var div = erb.parser;
        div.innerHTML = erb[selector](json);
        var fragment = document.createDocumentFragment();
        while (div.firstChild) {
            fragment.appendChild(div.firstChild)
        }
        return onsite ? el.parentNode.replaceChild(fragment, el) : fragment;

    }

    dom.erb.parser = document.createElement("div");
    dom.erb.startOfHTML = "/t__views.push(";
    dom.erb.endOfHTML = ");/n";
    dom.erb.rAt = /(^|[^/w/u00c0-/uFFFF_])(@)(?=/w)/g;


    window.dom = dom;
})();

PS:发现javascript模板没有想象中的糟糕,尤其是大流量的页面在无法使用UI库的情况下,这是个不错的选择,例子如qq zoneニコニコ動画

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值