artTemplate 动态加载模版

问题 

  以前项目中一直有用到artDialog对话框组件,做者后期又发布了js模版引擎,使用过几回,效果感受还挺好。当本身想把模版放在html以外时,遇到了一点问题。css

  做者介绍的方式,是在js文件中,经过定义变量,拼接模版,示例以下:html

var source =
  '<ul>'
+    '<% for (var i = 0; i < list.length; i ++) { %>'
+        '<li>索引 <%= i + 1 %> :<%= list[i] %></li>'
+    '<% } %>'
+ '</ul>';

var data = {
    list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};

var render = template.compile(source);
var html = render(data);
document.getElementById('content').innerHTML = html;

  我的很不喜欢这种方式,虽然做者有数据证实,用加号拼接字符串,在现代浏览器中,性能十分强劲,但模版看起来很是不直观。修改起来很郁闷,有时候一个逗号错误,一上午就过去了。相比之下,我仍是很喜欢在页面里配置的这种方式:前端

<script id="test" type="text/html">
<h1><%=title%></h1>
<ul>
    <%for(i = 0; i < list.length; i ++) {%>
        <li>条目内容 <%=i + 1%><%=list[i]%></li>
    <%}%>
</ul>
</script>

  这样看起来比拼接的舒服一点,并且容易修改。jquery

  问题就来了,能不能二者兼得呢?git

解决方案

  首先在外部定义模版,我采用的是模版提供的简便语法,但愿了解更多点击这里github

using System;
namespace Model
{
    public class {{name}}
    {
        {{each data}}
        /// <summary>
        /// {{$value.列说明}}
        /// </summary>
        public {{$value.数据类型}} {{$value.列名}} { get; set; }
        {{/each}}
    }
}

  接着,Html底部添加srcipt标记,指向上述模版地址。ajax

<script type="text/html" id="tmModel" src="template/model.txt"></script>

  接下来要处理的则是经过ajax根据路径获取到模版内容,而后编译它,编译完成后便可使用了。关键代码以下:后端

(function () {
    var tems = document.getElementsByTagName('script');

    for (var i = 0; i < tems.length; i++) {
        var t = tems[i];
        if (!t.id || !t.id.length || !t.src || !t.src.length || 'text/html' != t.type) continue;
        var obj = { src: t.src, id: t.id };
        //清除原来的模板信息
        t.id = "";
        t.src = "";
        ajaxrequest(obj.src, 'get', true, null, function (http, obj) {
            //预编译模版
            template.compile(obj.id, http.responseText.replace(/^\s*|\s*$/g, ""));
        }, obj);
    }
})();

  其中加载模版时,我采用的是Get方式 同步加载,避免模版未编译就使用。浏览器

  模版在加载完毕后,便可使用。看官方的语法:异步

 var html = template.render('tmTab', { data:[]});//tmTab 是咱们以前定义的Script标签ID,编译完成后,便可直接使用该模版

  html则是根据模版+数据编译后的html代码了。

  拓展的js代码以下,不依赖jquery:

/**
 * 获得ajax对象
 */
function getajaxHttp() {
    var xmlHttp;
    try {
        // Firefox, Opera 8.0+, Safari
        xmlHttp = new XMLHttpRequest();
    } catch (e) {
        // Internet Explorer
        try {
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                alert("您的浏览器不支持AJAX!");
                return false;
            }
        }
    }
    return xmlHttp;
}
/**
 * 发送ajax请求
 * url--url
 * methodtype(post/get)
 * con (true(异步)|false(同步))
 * parameter(参数)
 * functionName(回调方法名,不须要引号,这里只有成功的时候才调用)
 * (注意:这方法有二个参数,一个就是xmlhttp,一个就是要处理的对象)
 * obj须要到回调方法中处理的对象
 */
function ajaxrequest(url, methodtype, con, parameter, functionName, obj) {
    var xmlhttp = getajaxHttp();
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4) {
            //HTTP响应已经彻底接收才调用
            functionName(xmlhttp, obj);
        }
    };
    xmlhttp.open(methodtype, url, con);
    xmlhttp.send(parameter);
}



(function () {
    var tems = document.getElementsByTagName('script');

    for (var i = 0; i < tems.length; i++) {
        var t = tems[i];
        if (!t.id || !t.id.length || !t.src || !t.src.length || 'text/html' != t.type) continue;
        var obj = { src: t.src, id: t.id };
        //清除原来的模板信息
        t.id = "";
        t.src = "";
        ajaxrequest(obj.src, 'get', true, null, function (http, obj) {
            //预编译模版
            template.compile(obj.id, http.responseText.replace(/^\s*|\s*$/g, ""));
        }, obj);
    }
})();
templateExtension.js

最后

  相比使用MVC的Razor视图引擎,我的更倾向于使用js类的前端模版。

  在我看来,用户最后看到的网页,无非就是网页+数据。 网页呈现这一部分,根据业务类别如何显示,彻底交给html js css来作,后端无论是语言,提供相应的数据便可。

  固然,过多的ajax可能不利于SEO,不过我一直作的,都是内网用的,可能根本就不须要SEO。

  一点拙见,欢迎你们指正。

相关文章
相关标签/搜索