在我的一篇关于智能搜索框异步加载数据的文章中,有博友给我留言,认为我手写字符串拼接效率过低,容易出错。在经过一段时间的摸索和学习之后,发现现在拼接字符串的方法都不在是自己去书写了,而是使用Javascript引擎。而javascript引擎的实质就是帮我们把带有JavaScript代码的伪THTML语句编译为HTML。

  如果有不了解的朋友,可以前往这两篇文章:

  淘宝购物车页面 PC端和移动端实战

  淘宝购物车页面 智能搜索框Ajax异步加载数据

  源码地址:

  GitHub:Uncle-Keith

  回归正题,以下对artTemplate模板引擎的介绍会分为如下几部分内容:

  1.artTemplate模板引擎的基本语法结构

  2.artTemplate模板引擎的基本使用方法

    2.1:使用一个type="text/html"script标签存放模板

    2.2:在javascript中存放模板

    2.3:嵌入子模板(include)

  3.artTemplate模板引擎使用实战

 

1.artTemplate基本语法结构

  artTemplate的语法结构很简单,就是{{}}。{{}} 符号包裹起来的语句则为模板的表达式。表达式又分为 输出表达式,条件表达式,遍历表达式,模板包含表达式。具体的可以看看GitHub:artTemplate 简洁语法版。官网对语法介绍的还可以,不过在这里想在说一句,要记住表达式的写法和表达式有哪些分类,对于理解引擎很有帮助。

2.artTemplate模板引擎的使用方法

  首先,需要去官网下载 简洁语法版,然后在body底部加载script文件。文件很小,只有2.7kb,可是功能十分强大。

  2.1:使用一个type="text/html"script标签存放模板

    使用script存放模板的时候要注意两个方面。

    一方面是必须给script标签定义id,而且只能是id,不能是class。因为在使用template(id,data)方法的时候,该方法会根据id渲染模板,引擎内部会根据document.getElementById(id)查找模板。如果使用class作为参数,artTemplate引擎会报错。如果没有 data 参数,将返回一渲染函数。

    另外一方面是在<!DOCTYPE html>script标签中的type类型默认为type/javascript。在script标签中,必须重新声明type类型为text/html,否则会没有效果。

    使用方法如下

     <script id="test" type="text/html">
        <h1>{{title}}</h1>
        <ul>
            {{each list as value i}}
                <li>索引{{i+1}} : {{value}}</li>
            {{/each}}
        </ul>
     </script>
     <script>
         var data = {
             title:'My Life',
             list:['篮球','桌球','游泳','滑轮','读书']
         };
         var html = template('test',data);
         $('.rascal').html(html);
     </script>

    渲染的页面如下:

    

  2.2:在Javascript中存放模板

    在Js中存放模板应该会很少用到,因为在前端领域有一条军规,结构样式和行为三者必须分离。如果把模板放在js文件内,会破坏这条规定。

    看看例子,知道一下调用的规则。实质上就是一段拼接字符串的过程。

     <script type="text/javascript">
         var source ="<ul>"
         + "{{each list as value i}}"
         + "<li>索引{{i+1}}:{{value}}</li>"
         + "{{/each}}"
         + "</ul>";

         var render = template.compile(source);
         var html = render({
             list:['篮球','桌球','游泳','滑轮','读书']
         });

         $('.rascal').html(html);
     </script>

    

  2.3:嵌入子模板(include)

    嵌套模板跟第一种方法原理相同,只不过在一个模板中调用了另外一个模板而已。

     <script id='test' type='text/html'>
         <h1>My Life</h1>
         {{include 'list'}}
     </script>
     <script id='list' type='text/html'>
         <ul>
             {{each list as value i}}
                     <li>索引{{i+1}}:{{value}}</li>
             {{/each}}
         </ul>
     </script>
     <script>
         var data = {
             "list":['篮球','桌球','游泳','滑轮','读书']
         };
         var html = template('test',data);
         $('.rascal').html(html);
     </script>

    

3.artTemplate模板引擎使用实战

  artTemplate官网给出的每一个例子其实都已经很好了,可以让每一个人都很容易的明白。不过我认为唯一的缺点就是,例子中的数据完全都是自己定义的。在实际开发中,用户看到的每一个商品数据是这样来的:首先后端攻城狮通过特定语法连接数据库,然后将从数据库中获取的数据转换成JSON格式,最后前端攻城狮在通过一些方法将JSON数据渲染到页面上。所以我们的数据不能自己瞎造,而是通过Ajax异步加载。

  在我的一篇 淘宝购物车页面 智能搜索框Ajax异步加载数据 文章中,一开始是使用手写拼接字符串的方法去拼接字符串,这种方法效率低,容易出错。后来全部改成了js模板引擎的方法。所以我会以淘宝购物车页面中智能搜索框Ajax异步加载商品数据的例子来说明artTemplate模板引擎。

  先放上一段代码。主要还是想通过这个简单的例子说明接下来要探讨的问题。

     <script id="test" type="text/html">
        <h1>{{title}}</h1>
        <ul>
            {{each list as value i}}
                <li>索引{{i+1}} : {{value}}</li>
            {{/each}}
        </ul>
     </script>
     <script>
         var data = {
             title:'My Life',
             list:['篮球','桌球','游泳','滑轮','读书']
         };
         var html = template('test',data);
         $('.rascal').html(html);
     </script>

  上面代码中,要注意几点的就是:

  ♥ 遍历表达式中的list必须与脚本中data对象中的list同名,而且遍历表达式中的list必须是data对象中的一个属性。循环表达式中,要循环的是每一个data对象中的list数组,而不是data对象,这点很重要。

  在这个例子中,data对象中list属性是一个数组,数组中的每一个值都是简单数据类型,篮球桌球等。当然,可以往数组中传入复杂数据类型,如对象。说明这个主要是因为在循环表达式中循环的数据和给template()传入第二个参数的时候很容易出错。

  ♥ 使用template方法时,第一个参数必须是id,而不能是class。

  

  放上一段json数据代码。

[
    [
        {
            "Query":"lan",
            "Results":[
                {
                    "Type":"AS",
                    "Suggests":[
                        {
                            "Txt":"李宁2016新款男子篮球鞋音速3高帮反弹篮球场地鞋ABAL031",
                            "num":339,
                            "max":764,
                            "discount":200,
                            "label":"liningBas",
                            "shop":"李宁官方网店",
                            "image":"css/images/lining-bas.png",
                            "color":"颜色分类:荧光果粉/木梅红",
                            "size":"鞋码:42",
                            "nonDiscount":"¥539.00",
                            "bandCard":"css/images/bankCard.png",
                            "sevenDay":"css/images/sevenDay.png",
                            "guarantee":"css/images/guarantee.png"
                        },
                        {
                            "Txt":" adidas阿迪达斯篮球男子篮球鞋Regulate",
                            "num":419,
                            "max":18,
                            "discount":120,
                            "label":"adidas",
                            "nonDiscount":"¥539.00",
                            "image":"css/images/adidas.png",
                            "color":"颜色分类:银金属/深藏青蓝",
                            "shop":"adidas官方旗舰店",
                            "size":"鞋码:43.5",
                            "bandCard":"css/images/bankCard.png",
                            "sevenDay":"css/images/sevenDay.png",
                            "guarantee":"css/images/guarantee.png"
                        }
                    ]
                }
            ]
        }
    ],
    [
        {
            "Query":"音速3",
            "Results":[
                {
                    "Type":"AS",
                    "Suggests":[
                        {
                            "Txt":"李宁2016新款男子篮球鞋音速3高帮反弹篮球场地鞋ABAL031",
                            "num":339,
                            "max":764,
                            "label":"liningBas",
                            "shop":"李宁官方网店",
                            "image":"css/images/lining-bas.png",
                            "color":"颜色分类:荧光果粉/木梅红",
                            "size":"鞋码:42",
                            "nonDiscount":"¥539.00",
                            "bandCard":"css/images/bankCard.png",
                            "sevenDay":"css/images/sevenDay.png",
                            "guarantee":"css/images/guarantee.png"
                        }
                    ]
                }
            ]
        }
    ]
]

basketBallShoes.json

  上面代码中,是一段需要被Ajax异步加载数据的商品数据。

  再放上使用一个type="text/html"script标签存放模板的代码。

    <script id='basketBallShoes' type="text/html">
        {{each Suggests as value i}}
            <div class="mainCommodity">
                <div class="shopInfo">
                    <div class="shopMsg">
                            <input type="checkbox" name="shopMsg" id='{{value.label}}' class='shopMsg-input' autocomplete="off">
                            <label for="{{value.label}}">店铺:
                        <a href="#">{{value.shop}}</a>
                    </div>
                </div>
                <div class="commodityInfo">
                    <ul>
                        <li class='td-chk'>
                            <div class="td-inner">
                                <input type="checkbox" name='checkbox' autocomplete="off" >
                            </div>
                        </li>
                        <li class='td-item'>
                            <div class="td-inner">
                                <a href="#" class='desImg'>
                                    <img src="{{value.image}}" alt='{{value.Txt}}'>
                                </a>
                                <div class="item-info">
                                    <div class="item-basis-info">
                                        <a href="#">{{value.Txt}}</a>
                                    </div>
                                    <div class="item-other-info">
                                        <div class="item-other-space"></div>
                                        <div class="item-other-list">
                                            <a href="#" title='支持信用卡支付'>
                                                <img src="{{value.bandCard}}" alt="支持信用卡支付">
                                            </a>
                                            <a href="#" class='sevenDay' title='7天无理由'>
                                                <img src="{{value.sevenDay}}" alt="7天无理由">
                                            </a>
                                            <a href="#" title='消费者保障服务'>
                                                <img src="{{value.guarantee}}" alt="消费者保障服务">
                                            </a>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </li>
                        <li class='td-info'>
                            <div class="td-info-msg">
                                <p>{{value.color}}</p>
                                <p>{{value.size}}</p>
                            </div>
                        </li>
                        <li class='td-price'>
                            <div class="td-inner">
                                <p class='non-discount'>{{value.nonDiscount}}</p>
                                <p class='discount'>¥<span>{{value.num}}.00</span></p>
                                <div class="promotion">
                                    卖家促销
                                    <i class='promotionIcon'></i>
                                </div>
                                <div class="proSlidedown">
                                    <p class='newPro'>卖家促销:新品大特价</p>
                                    <p>优惠:¥200.00</p>
                                </div>
                            </div>
                        </li>
                        <li class='td-amount'>
                            <div class="item-amount">
                                <a href="#" class='amount-left amount-color'>-</a>
                                <input type="text" name='amountNum' value='1' autocomplete="off">
                                <a href="#" class="amount-right">+</a>
                            </div>
                            <div class="stock">
                                {{value.max}}
                            </div>
                            <div class="outNum">
                                <span class="instr">最多只能购买</span>
                                <span class='stockNum'></span><!--
                                --><em>件</em>
                            </div>

                            </li>
                        <li class='td-sum'>
                            <em>¥</em><!--
                            --><span>{{value.num}}</span>
                        </li>
                        <li class='td-operation'>
                            <p><a href="#" class='delete'>删除</a></p>
                        </li>
                    </ul>
                </div>
            </div>
        {{/each}}
    </script>
    <script id="search" type="text/html">
        <ul>
            {{each Suggests as value i}}
                <li>{{value.Txt}}</li>
            {{/each}}
        </ul>
    </script>
    <script id='delete' type='text/html'>
        <div class="undo-wrapper">
            <div class="deleteCom">
                <p>
                    成功删除
                    <em>1</em>
                    件宝贝,如果有无,可
                    <a href="#" class='turnBack'>撤销本次删除</a>
                </p>
            </div>
        </div>
    </script>

JS模板引擎

  上面代码中是需要被渲染的模板。比手写拼接字符串简单很多,并且效率高,错误率低。

  最后放上js实现相应功能的部分重要代码。

$.get('search.json',{'Query':$val}, function(data) {
    for (var i = 0; i < data.length; i++) {
        //如果值与json中的query字段匹配,动态加载html
        if ($val === data[i][0].Query) {
        var results = data[i][0].Results[0];
        //js模板引擎
        var $html = template('search',results);
        $('.list').html($html)
        }
    }
});

  这里想说的是给template方法的第二个参数和循环表达式需要被循环的字段。

  第一点是给template方法的第二个参数。第二个参数传入了results,这里的results实质上就是在上面例子中data对象。只不过在JSON数据中results是一个数组。

  第二点是在JS模板引擎中。在模板中是这样写的:{{each Suggests as value i}},这里的Suggests其实就相当于data对象中的list属性。在data对象中,list是一个数组,并且每个值都是字符串;而在results数组中,Suggests是一个数组,不过它的每一个值都是复杂数据类型,是对象。如果对数据类型不明白的,可以前往这篇文章:Javascript对象

  

  artTemplate使用实战就介绍完了。在template方法的第二个参数和遍历表达式中需要被遍历的数据很容易写错,希望同学可以注意这一点。

  如果有不明白或者写错的地方,可以给我留言。

  参考文章

  artTemplate

  atc-前端模板预编译器

  高性能JavaScript模板引擎原理解析

  最简单的JavaScript模板引擎

  简单JavaScript模版引擎优化

  javascript模板引擎原理,几行代码的事儿

  大叔手记(7):构建自己的JavaScript模板小引擎

  基于HTML模板和JSON数据的JavaScript交互

  源码地址:GitHub:Uncle-Keith

  转载请注明出处:http://www.cnblogs.com/Uncle-Keith/p/5932439.html

  完。感谢大家的阅读。

artTemplate模板引擎学习实战的更多相关文章

  1. Node学习之(第三章:art-template模板引擎的使用)

    前言 大家之前都有使用过浏览器中js模板引擎,其实在Node.js中也可以使用模板引擎,最早使用模板引擎的概念是在服务端新起的. art-template art-template是一款高性能的Jav ...

  2. C#模板引擎NVelocity实战项目演练

    一.背景需求 很多人在做邮件模板.短信模板的时候,都是使用特殊标识的字符串进行占位,然后在后台代码中进行Replace字符串,如果遇到表格形式的内容,则需要在后台进行遍历数据集合,进行字符串的拼接,继 ...

  3. artTemplate模板引擎

    artTemplate模板引擎         <li>索引 {{i + 1}} :{{value}}</li>     {{/each}} </ul> </ ...

  4. NVelocity模板引擎学习笔记

    NVelocity模板引擎学习笔记 学习模板引擎有一段时间现在做一些总结

  5. koa art-template模板引擎的使用

    art-template 模板引擎介绍 art-template 是一个简约.超快的模板引擎. 它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行 性能,并且同 ...

  6. Express 中配置使用 art-template模板引擎

    art-template 官网 https://aui.github.io/art-template/ 安装: npm install --save art-template npm install ...

  7. artTemplate模板引擎的源码拜读

    最初接触的模板引擎还是基于node的ejs,当时觉得很神奇原来还可以这么玩,后来随着学习的深入,使用过jade,doT等,当然还有一些比较火的诸如juicer.underscore还没有深入接触,直到 ...

  8. jade模板引擎学习笔记(WebsStorm9.0.3+ nodejs+express+jade)

    jade环境搭建 jade标签写法 jade注释 jade添加类名.id.属性 jade添加脚本,css jade变量 jade多行文本显示 jade流程代码:for,each,while jade流 ...

  9. 第115天:Ajax 中artTemplate模板引擎(一)

    一.不分离与分离的比较 1.前后端不分离,以freemarker模板引擎为例,看一下不分离的前后端请求的流程是什么样的? 从上图可以看出,前后端开发人员的工作耦合主要在(3)Template的使用.后 ...

随机推荐

  1. Ajax_02之XHR发起异步请求

    1.Ajax: AJAX:Asynchronous Javascript And Xml,异步的JS和XML: 同步请求:地址栏输入URL.链接跳转.表单提交-- 异步请求:使用Ajax发起,底层使用 ...

  2. c#方法

    1.引用型参数: 关键字:ref 2.输出型参数 关键字:out 例: double area(out double p) { double t=3.14*10; p=2*t*3.14; return ...

  3. Entity Framework 6 Code First新特性:支持存储过程

    Entity Framework 6提供支持存储过程的新特性,本文具体演示Entity Framework 6 Code First的存储过程操作. Code First的插入/修改/删除存储过程 默 ...

  4. es6学习笔记一数组(中)

    接着上一篇,给大家再分享一些数组的其他方法.大家也可以去点击这里学习数组更多的方法 concat方法: 概述:    concat() 方法将传入的数组或非数组值与原数组合并,组成一个新的数组并返回. ...

  5. 前端学PHP之变量范围

    × 目录 [1]范围跨度 [2]函数范围 [3]global[4]预定义变量[5]超全局变量 前面的话 变量范围即它定义的上下文背景(也就是它的生效范围).在javascript中,并没有变量范围这一 ...

  6. Git 冲突合并

    在多人协作开发,经常遇到Git冲突,每次都不大记住命令.所以自己备注一下! git pull 之后有冲突: $ git pullremote: Counting objects: 5, done.re ...

  7. (十七)WebGIS中距离及面积测量的原理和实现以及坐标转换的简单介绍

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在这一章里我们将讨论基础工具栏中另外两个常用工具:距离测量工 ...

  8. 用Vagrant和Ansible搭建持续交付平台

    这是一个关于Vagrant的学习系列,包含如下文章: Vagrant入门 创建自己的Vagrant box 用Vagrant搭建Jenkins构建环境 用Vagrant和Ansible搭建持续交付平台 ...

  9. CoCreateInstance调用返回代码0x80040154的一种解决方法

    引言 前面的一篇博文中总结了开发Windows Thumbnail Handler的一些经验.在公司实际项目中,需要同时针对图片和视频实现缩略图.同时还要在图片和视频文件的顶部加上LOGO.像如下这样 ...

  10. 从 AJAX 到 JSONP的基础学习

    目录索引: 一.AJAX的概念二.POST && GET三.原生实现AJAX简单示例 3.1 实现代码 3.2 重点说明四.框架隐藏域 4.1 基本概念 4.2 后台写入脚本 4.3 ...