JsRender前端渲染模板

使用模板,可以预先自定义一些固定格式的HTML标签,在需要显示数据时,再传入真实数据组装并展示在Web页中;避免了在JS中通过“+”等手动分割、连接字符串的复杂过程;针对高性能和纯字符串渲染进行了优化;无需依赖DOM和jQuery;

优先使用场景:元素重复出现;动态加载数据,并前端显示;

JsRender使用

  1. 引入js
  2. 定义模板
  3. 准备好要显示的数据 json对象
  4. 编译成元素:document.getElementById(“XXX”).render(data); 或 $("#XXX").render(data);
  5. 通过容器元素的append、before、after显示

一、基本语法

  • 原始赋值: {{:属性名}},显示原始数据
  • 转码赋值: {{>属性名}},显示HTML编码后的数据,让数据原样输出
  • 控制语句可嵌套使用:
  • 判断: {{if 表达式}} … {{else}} … {{/if}}
  • 循环: {{for 数组}} … {{/for}}
  • 其它进阶
  • 模板嵌套,使用:{{for tmpl="#另一个模板" /}}
  • 转换器 $.views.converters()定义,使用:{{func:属性名}}
  • 帮助方法 $.views.helpers()定义,使用:{{if ~func(arg1, arg2, ...)}}
  • 自定义标签 $.views.tags()

基本变量标签 {{:name}}

基本变量需要使用冒号 ":" 作为标识,一般是简单对象的某个属性。比如传入一个简单对象data

引入jquery-3.2.1.min.js 和 jsrender.min.js

<script src="/Scripts/jquery-3.2.1.min.js"></script>
<script src="/Content/jsrender.min.js"></script>
<body>
    <div id="result"></div>

    <script type="text/x-jsrender" id="Tmpl">
        <p>Name: {{:name}}</p>
        <p>Age: {{:age}}</p>
    </script>

    <script>
        var data = {
            'name': 'van',
            'age': 18
        }

        var html2 = $("#Tmpl").render(data);
        $("#result").append(html2);
    </script>
</body>

传入一个多层级对象data

javascript数据渲染 js模板渲染_jsrender.js

javascript数据渲染 js模板渲染_JsRender_02

<div id="result"></div>

    <script type="text/x-jsrender" id="Tmpl">
        <p>Name: {{:Info.name}}</p>
        <p>Age: {{:Info.age}}</p>
        <p>{{:Details.Address}}</p>
        <p>{{:Details.Hobby.TableTennis}}</p>
    </script>

    <script>
        var data = {
            'Info': {
                'name': 'van',
                'age': 18
            },
            'Details': {
                'Hobby': {
                    'TableTennis': 'I like Table Tennis',
                    'Basketball': 'I like Basketball'
                },
                'Address': 'My address'
            }
        }

        var html2 = $("#Tmpl").render(data);
        $("#result").append(html2);
    </script>

View Code

如上所见,不管传入的对象有多复杂,都能按照层级去找到属性,只是把最外层的对象名 data 省略掉了

启用与定义全局变量的标签{{*}}与 {{*:}}

{{*count = 1}}
<p>{{*:count + 2}}</p>

$.views.settings.allowCode(true);

首先需要执行$.views.settings.allowCode(true);,把设置开启,然后使用{{*count = 1}}定义一个变量,然后再用{{*:count}}引用变量。当然,jsrender也提供了只有某一个模板支持全局变量的设置方式

var tmpl = $.templates({
    markup: "#myTemplate",
    allowCode: true
  });

 注释标签 {{!--    --}}

<p>{{!--:Details.Address--}}</p>

条件判断语句 {{if condition}} ... {else condition} ... {{else}}... {{/if}}

jsrender 的 if else 语法跟正常的代码逻辑还是有点区别的,当只有两种情况的时候,是没有区别的,就是 if else

<body>
    <div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        <p>姓名: {{:name}}</p>
        <p>
            我是:
            {{if info.age >= 18}}
            成年人
            {{else}}
            未成年
            {{/if}}
        </p>
    </script>
    <script>
        var data = {
            "name": "van",
            info: {
                "age": 22
            }
        };
        var html = $("#tmp").render(data);
        $("#result").html(html);
    </script>
</body>

但是当有多种情况的时候,也就是 if ... else if ... else if ... else 的时候,可是jsrender并没有 else if 这样的写法,它会根据情况来判断,如果是多重情况,它会自动把 else 当做 else if来使用

<script type="text/x-jsrender" id="tmp">
        <p>姓名: {{:name}}</p>
        <p>
            {{if info.age >= 18}}
              大于18岁
            {{else info.age >= 16&&info.age < 18}}
              大于16岁小于18岁
            {{else}}
              未成年
            {{/if}}
        </p>
    </script>

if  else 除了以 {{if}}....{{/if}} 的形式使用,也可以使用 {{if xxx=true ... /}} 自闭合的形式,而且还可以引入模板,也可以混着用

<script type="text/x-jsrender" id="tmp">
        <p>姓名: {{:name}}</p>
        <p>
            {{if info.age >= 18 tmpl="#tmp2" /}}                                     
            {{if name=="van"}}
              帅~
            {{else}}
              依旧帅~
            {{/if}}
        </p>
    </script>
    <script type="text/x-jsrender" id="tmp2">
        <h3>大于18岁</h3>
    </script>

使用  {{for}} ... {{/for}} 循环对数据进行循环或对对象进行遍历

jsrender的for循环会默认把数组或对象的第一层循环遍历掉,我们只要管里面的数据就行了,而且使用了循环之后的模板也可以单独写成一个模板,在for循环中引用,循环数组的时候可以使用 {{:#index}} 来获取当前数组的下标,并且index是从0开始的,提醒:尽量使用#getIndex()获取索引,避免使用#index,除非你的应用足够简单。

<div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        {{!-- data 对象已经被默认遍历,所以属性前不用加 data. 就可访问到 --}}
        <h3>there have {{:kind}} kinds animal</h3>
        <p>and the cow price is {{:price.cow}}</p>
        <p>and the cow price is {{:price.pig}}</p>

        {{!-- 也可以这样对对象进行for循环 --}}
        {{for price}}
        <p>and the cow price is {{:cow}}</p>
        <p>and the cow price is {{:pig}}</p>
        {{/for}}

        <ul>
            {{!-- 对对象数组进行循环 --}}
            {{for list}}
            <li>{{:#getIndex() + 1}}. this animal call {{:name}}, and has {{:count}}, it has {{:foot}} foots</li>
            {{/for}}
            {{!-- 也可以使用模板引入作为循环的模板 --}}
            {{for list tmpl="#tmp2" /}}
        </ul>

    </script>
    <script type="text/x-jsrender" id="tmp2">
        <li>{{:#getIndex() + 1}}. this animal call {{:name}}, and has {{:count}}, it has {{:foot}} foots</li>
    </script>

    <script>
        var data = {
            'kind': 4,
            'price': {
                'cow': 19999,
                'pig': 1888
            },
            'list': [
                {
                    'name': 'cow',
                    'count': 4,
                    'foot': 4
                },
                {
                    'name': 'chicken',
                    'count': 5,
                    'foot': 2
                }
            ]
        }

        var html = $("#tmp").render(data);
        $("#result").html(html);
    </script>

嵌套for

<div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        {{for}}
        <li>
            Name:{{:name}}
            <ul>
                {{for hobbies}}
                <li>{{:#getIndex() + 1}}-{{:#data}}</li>
                {{/for}}
            </ul>
        </li>
        {{/for}}
    </script>

    <script>
        var data = [
          { name: "tom", hobbies: ["篮球", "足球"] },
          { name: "jack", hobbies: ["篮球", "橄榄球"] },
          { name: "lucy", hobbies: ["游泳", "羽毛球"] }
        ];
        var html = $("#tmp").render(data);
        $("#result").html(html);
    </script>

嵌套循环使用参数访问父级数据

<table border="1">
        <thead>
            <tr>
                <th>序号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>家庭成员</th>
            </tr>
        </thead>
        <tbody id="result"></tbody>
    </table>

    <script type="text/x-jsrender" id="tmp">
        {{for}}
        <tr>
            <td>
                {{:#getIndex() + 1}}
            </td>
            <td>{{:name}}</td>
            <td>{{:age}}</td>
            <td>
                {{!-- 使用for循环时,可以在后边添加参数,参数必须以~开头,多个参数用空格分隔 --}}
                {{!-- 通过参数,我们缓存了父级的数据,在子循环中访问参数,就可以间接访问父级数据 --}}
                {{for family ~parentIndex=#getIndex() ~parentName=name ~parnetAge=age}}
                <b>{{:~parentIndex + 1}}.{{:#getIndex() + 1}}</b>
                {{!-- #data相当于this --}}
                {{:~parentName}}的{{:#data}}
                {{/for}}
            </td>
        </tr>
        {{/for}}
    </script>
    <script>
        var data = [
            {
                name: "张三",
                age: 3,
                family: ["爸爸", "妈妈", "哥哥"]
            },
            {
                name: "李四",
                age: 4,
                family: ["爷爷", "奶奶", "叔叔"]
            }
        ];
        var html = $("#tmp").render(data);
        $("#result").html(html);
    </script>

当循环数组或者遍历对象的时候,如果在 {{for}} {{/for}} 中间加上 {{else}},还可以对遍历的对象进行判断,如果该对象或者属性不存在,那么就显示其他的内容。

{{!-- 遍历的时候顺便判断merbers是否存在 --}}
{{for members}}
    <div>{{:name}}</div>
{{else}} 
    <div>No members!</div>
{{/for}}

 使用 {{props}} 遍历对象并且获取到对象的key/value

当我们遍历对象需要使用到对象的key值时,使用props可以获取到key/value值,而且也可以在for循环中进行对象的遍历,在数据循环中获取可以使用#data获取到当前的对象,当然也可以使用引入外部模板来当做循环模板。

<div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        {{!-- 简单的对象遍历 --}}
        {{props price}}
        <p>the {{:key}} price is {{:prop}}</p>
        {{/props}}
        <ul>
            {{!-- 在数据循环中再进行对象的遍历,病获取到key/prop --}}
            {{for list}}
            <li>
                {{:#index + 1}}.
                {{props #data}}
                <b>{{:key}}</b> is {{>prop}}
                {{/props}}
            </li>
            {{/for}}

            {{!-- 也可以使用模板引入作为循环的模板 --}}
            {{for list tmpl="#tmp2" /}}

        </ul>
    </script>
    <script type="text/x-jsrender" id="tmp2">
        <li>
            {{:#index + 1}}.
            {{props #data}}
            <b>{{:key}}</b> is {{>prop}}
            {{/props}}
        </li>
    </script>

    <script>
        var data = {
            'kind': 4,
            'price': {
                'cow': 19999,
                'pig': 1888
            },
            'list': [
                {
                    'name': 'cow',
                    'count': 4,
                    'foot': 4
                },
                {
                    'name': 'chicken',
                    'count': 5,
                    'foot': 2
                }
            ]
        }

        var html = $("#tmp").render(data);
        $("#result").html(html);
    </script>

当然,也可以在prop遍历对象的时候对对象进行判断,只要在prop遍历中加入 {{else}},如果对象为undefined或对象为空,那么就执行else

{{props address}}
    <b>{{:key}}:</b>{{:prop}} <br />
{{else}} 
    The address is blank (no properties)!
{{/props}}

使用 {{include}} 引入外部模板或者改变模板的上下文

虽然我们可以在 {{for}} 循环中或者 {{if}} 标签中直接引入模板,但是 {{include}} 引入模板才是符合我们认知的,应该什么标签干什么事

<script type="text/x-jsrender" id="tmp">
        {{if case == 1}}
        {{include tmpl="#tmp1" /}}
        {{else case == 2}}
        {{include tmpl="#tmp2" /}}
        {{else}}
        <p>no data</p>
        {{/if}}
 </script>

使用{{include}}标签引入模板显得比较语义化,虽然并没有什么差别。除了引入模板,{{include}}还可以在引入模板的同时引入对象或者数组,来改变所引入模板的上下文

<div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        {{if case == 1}}
        {{include data tmpl="#tmp1" /}}
        {{else case == 2}}
        {{include data1 tmpl="#tmp2" /}}
        {{else}}
        <p>no data</p>
        {{/if}}
    </script>
    <script type="text/x-jsrender" id="tmp1">
        {{!-- for循环会默认取到传进来的对象 使用data.title是访问不到的 --}}
        {{!-- 传进来的对象必须手动循环 --}}
        {{for}}
        <h3>{{:title}}</h3>
        <p>{{:text}}</p>
        {{/for}}
    </script>
    <script type="text/x-jsrender" id="tmp2">
        {{!-- :length 可以获取当前数组的长度 --}}
        {{:length}}
        {{!-- 传进来的数组必须手动循环 --}}
        {{for #data}}
        <h3>{{:title}}</h3>
        <p>{{:text}}</p>
        {{/for}}
    </script>

    <script>
        var condition = {
            'case': 2,
            'data': {
                'title': 'this is first case',
                'text': 'case one text'
            },
            'data1': [
                {
                    'title': 'i am outer fisrt title',
                    'text': 'it is me,diffrent light'
                },
                {
                    'title': 'i am outer second title',
                    'text': 'it is me,diffrent light'
                }
            ]
        };

        var html = $("#tmp").render(condition);
        $("#result").html(html);
    </script>

使用 {{converters:value}} 把value转换成所需要的格式

当后端给我们返回的数据格式跟页面所展示的格式不一样的时候,我们就需要对数据进行转换。比如说后端返回时间的毫秒数,可是页面却要显示 年-月-日 的格式或者是后端返回小写的字符,页面却要显示成大写的字符,这个时候转换器就派上用场了。
jsrender提供了api $.views.converters()来注册转换方法。

<div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        <div>
            <h3>{{upper:name}}</h3>
            <p>{{:age}}</p>
        </div>
    </script>

    <script>
        var condition = {
            'name': 'van',
            'age': 20
        };

        $.views.converters({
            upper: function (val) {
                return val.toUpperCase();//转大写
            }
        })

        var html = $("#tmp").render(condition);
        $("#result").html(html);
    </script>

使用 {{:~helper(value)}} 对传入的参数value做处理

当我们拿到的数据不符合展示的需求是,我们需要对数据进行处理,那么我们可以使用辅助函数,把原始值当成参数传入,返回我们需要的数据。

jsrender提供了$.views.helper()方法来注册辅助函数。并使用~当前缀来调用辅助函数。

<div id="result"></div>

    <script type="text/x-jsrender" id="tmp">
        <div>
            <h3>{{:~hello(firstName, lastName)}}</h3>
            <p>{{:age}}</p>
        </div>
    </script>

    <script>
        var info = {
            firstName: 'van',
            lastName: 'wu',
            age: 18
        };

        $.views.helpers({
            hello: function (fisrtName, lastName) {
                return 'Hello ' + fisrtName + ' ' + lastName;
            }
        })

        var html = $("#tmp").render(info);
        $("#result").html(html);
    </script>

以上就是JsRender的基本用法,下篇会学习JsRender的一些常用API。