zoukankan      html  css  js  c++  java
  • JsRender 前端渲染模板常用API学习

    JsRender 常用API

    1. $.templates()

    $.templates()方法是用来注册或编译模板的,使用的情况有以下几种。

    • 把html字符串编译编译成模板
    • 获取使用script标签声明的模板,并返回一个模板对象
    • 把html字符串或者在script标签中声明的模板注册成命名模板
    • 获取之前就存在的命名模板
    • 在nodejs中,根据文件路径获取一个模板对象

    我们正常使用的方式就是使用$.templates()方法把html字符串编译成模板,返回一个模板对象,然后调用该对象的render方法并传入数据,就可以得到一份完整的html字符串代码。比如:

     <div id="result"></div>
    
        <script>
            var info = {
                name: 'van',
                age: 18
            };
    
            //获取模板
            var jsRenderTpl = $.templates('<div><h3>{{:name}}</h3><p>{{:age}}</p></div');
            //模板与数据结合
            var html = jsRenderTpl.render(info);
            //也可以这样用
            //var html = jsRenderTpl(info);
            $("#result").html(html);
        </script>

    或者我们也可以给模板定义一个名称

    //定义一个命名模板
    $.templates('myPersonalInfoTpl', '<div><h3>{{:name}}</h3><p>{{:age}}</p></div');
    //模板与数据结合
    var html = $.render.myPersonalInfoTpl(info);

    当然,我们也可以把html字符串单独写在script标签中,然后根据id来获取

     <div id="result"></div>
    
        <script type="text/x-jsrender" id="tmp">
            <div>
                <h3>{{:name}}</h3>
                <p>{{:age}}</p>
            </div>
        </script>
        <script>
            var info = {
                name: 'van',
                age: 18
            };
    
            //定义一个命名模板
            $.templates('myPersonalInfoTpl', '#tmp');
            //模板与数据结合
            var html = $.render.myPersonalInfoTpl(info);
            $('#result').html(html);
        </script>

    更想当然,还可以在一个templates()方法里面注册多个命名模板

    <div id="result"></div>
    
        <script type="text/x-jsrender" id="tmp">
            <div>
                <h3>{{:name}}</h3>
                <p>{{:age}}</p>
            </div>
        </script>
        <script>
            var info = {
                name: 'van',
                age: 18
            };
    
            //定义一个命名模板
            $.templates({
                'myPersonalInfoTpl': '#tmp',
                'externalTpl': '<p>this is externalTpl</p>'
            });
            //模板与数据结合
            var finalTpl = $.render.myPersonalInfoTpl(info);
            var externalTpl = $.render.externalTpl();
            $('#result').html(finalTpl).append(externalTpl);
        </script>

    还可以指定一些只供这个模板使用的一些方法

     <div id="result"></div>
    
        <script type="text/x-jsrender" id="tml">
            <div>
                <h3>{{upper:~append(name, ' wu')}}</h3>
                <p>{{:age}}</p>
            </div>
        </script>
    
        <script>
            var info = {
                name: 'van',
                age: 18
            };
    
            //定义一个命名模板,并指定只供这个模板使用的转换方法与辅助方法
            $.templates("myPersonalInfoTpl", {
                markup: "#tml",
                converters: {
                    upper: function (val) {
                        return val.toUpperCase();
                    }
                },
                helpers: {
                    append: function (a, b) {
                        return a + b;
                    }
                }
            });
            //模板与数据结合
            var finalTpl = $.render.myPersonalInfoTpl(info);
            $('#result').html(finalTpl);
        </script>

    2、渲染模板的render()方法

    当我们使用$.templates()方法注册一个模板对象时,最后还是需要把模板对象跟数据结合得到最终的html字符串的,render()的使用方式有以下三种。
    当模板对象myPersonalTpl是使用$.templates()注册的模板时,只能使用myPersonalTpl.render(data)的方式来渲染模板
      //定义一个匿名模板
      var myPersonalTpl = $.templates("#tml");
      //模板与数据结合
      var finalTpl = myPersonalTpl(info);

    当模板对象myPersonalTpl是以命名模板的方式注册时,需要使用$.render.myPersonalTpl(data)或者$.render['myPersonalTpl'](data)的方式来渲染模板

    //定义一个命名模板
    $.templates("myPersonalInfoTpl","#tml");
    //模板与数据结合
    var finalTpl = $.render.myPersonalInfoTpl(info);

    当使用jQuery、并且模板是在script标签中声明时,还可以直接使用$("#personTemplate").render(data),并不需要调用$.templates()方法来注册模板。

    var myHelpers = {
            upper: function(val){
                return val.toUpperCase();
            }
        }
        //使用jQuery选择器获取script标签声明的jsrender模板,并传入数据跟一些方法渲染模板。
        var html = $("#tml").render(data, myHelpers);
        $('select').html(html);
    3、 使用$.views.helpers()方法注册辅助函数
    当我们拿到的数据跟页面显示的数据有差别、或者是我们需要把原数据转化成其他格式的数据时,我们使用一些辅助函数来实现,jsrender提供了两种方式,一种是helper函数,一种是converters转换器。我们先讲辅助函数helper。helper方法是以 "~" 为前缀作为方法的标识,在加上方法名,然后把值当参数传进去
    //example
    {{:~myHelperValue}}
    {{:~myHelperFunction(name, title)}}
    {{for ~myHelperObject.mySortFunction(people, "increasing")}} ... {{/for}}

    辅助函数helper注册方式有以下三种:

    • 使用$.views.helpers()注册全局的helper方法。
      当我们需要一些比较通用的方法时,可以提取出来写到公用的js文件中去,以后就不用重新写一遍了。
    // 定义全局的helper方法
            $.views.helpers({
                concat: function(first , last){
                    return first + '  ' + last;
                },
                util: {
                    prefix: 'age is  ',
                    addPrefix: function(age){
                        return this.prefix + age;
                    }
                }
            });
    • 写局部的辅助方法
      当我们的某一个页面有多处使用一个辅助方法,但是又不够通用,不必写到common文件去时,我们可以写只供这个页面使用的辅助方法。
    // 定义局部的helper方法
            var myHelper = {
                concat: function(first , last){
                    return first + '  ' + last;
                },
                util: {
                    prefix: 'age is  ',
                    addPrefix: function(age){
                        return this.prefix + age;
                    }
                }
            }
    
            //并在渲染模板的时候把myHelper当做参数传进去
            var html = $('#tml').render(data, myHelper);
    • 只给特定的模板写辅助函数,其实也就是在定义模板的时候把helper传进去
    //注册一个命名模板,并指定helper方法
            $.templates({
                myPersonInfo: {
                    markup: '#tml',
                    helpers: {
                        concat: function(first , last){
                            return first + '  ' + last;
                        },
                        util: {
                            prefix: 'age is  ',
                            addPrefix: function(age){
                                return this.prefix + age;
                            }
                        }
                    }
                }
            });
    
            //渲染模板,命名模板只能使用$.render调用
            var html = $.render.myPersonInfo(data);
            $('#box').html(html);

    4、使用$.views.converters()注册转换器

    在jsrender中,转换器主要是方便对数据或表达式的的结果进行处理或者格式化,jsrender本身自带了三个转换器,比如:
    {{html:'<b>bolin</b>'}} //- 对html标签进行编码,原样输出 :<b>bolin</b>
    {{>'<b>bolin</b>'}} //同上,html的别名
    {{url:"<_>_\"_'"}} // 对特殊字符进行编码 基本是 <,>,",'...    :%3C_%3E_%22_'
    {{attr:value}} //对标签的属性值进行编码,也是字符的转换

    当然,仅仅是这三个转换时不够用的,jsrender提供了自定义转换器的方法。$.views.converters()。比如我想要定义一个时间格式化的转换器跟大小写转换的转换器。

     <div id="result"></div>
    
        <script type="text/x-jsrender" id="myPersonInfo">
            <h3>{{upper: 'my name is ' + name}}</h3>
            <p>now is {{dateFormat: time}}</p>
        </script>
        <script>
            var data = {
                name: 'van',
                time: new Date()
            };
    
            //注册全局转化器
            $.views.converters({
                dateFormat: function (val) {
                    var time = new Date();   
                    return (time.getMonth() + 1) + '' + time.getDate() + '';
                },
                upper: function (val) {
                    return val.toUpperCase();
                }
            });
    
            //渲染模板,命名模板只能使用$.render调用
            var html = $('#myPersonInfo').render(data);
            $('#result').html(html);
        </script>

    你会发现,其实转换器跟辅助函数差不多,只是使用的方法不一样而已。虽然实现都差不多,但还是有点区别的,转换器也分全局定义跟局部定义,局部定义的转换只要把模板当做参数传进去就好了,所定义的转换器只能在此模板中生效。

     //注册局部转换器,指定myPersonInfo模板可用
            $.views.converters({
                dateFormat: function (val) {
                    var time = new Date();
                    return (time.getMonth() + 1) + '月' + time.getDate() + '日';
                },
                upper: function (val) {
                    console.log(val);
                    return val.toUpperCase();
                }
            }, $.templates('#tml'));

    除了使用在{{convert:}}标签中之外,还可以在{{if}},{{for}}标签中使用,语法如下:

    //if语句
    {{if convert='inList' }}...{{/if}}
    //for语句
    {{for people convert='even'}}...{{/for}}

    在其他标签中使用时,只是需要把转化器赋值给convert,当然也可以把辅助方法赋值给convert,比如

    {{:name convert=~hlp.bold}}
    但是呢,如果你使用{{>name convert=~hlp.bold}}的话,是会报错的,还是老老实实使用辅助方法的形式,除了以上的使用方式之外,convert还提供了一些比较好的功能,比如使用this.tagCxt.props可以获取到标签中定义的属性,使用this.tagCxt.view.data可以获取到标签中所有的变量。
    5、使用$.views.tags()注册自定义标签

    jsrender 提供了一些内置的标签,但往往是不够用的,所以提供了$.views.tags()方法来定义一些比较灵活的标签。自定义标签比较灵活,能控制、访问的元素也比较多,比如写在该标签里面的args、props、甚至整个view model对象里面的全部数据。使用$.views.tags注册自定义标签的语法有以下四种

    1. $.views.tags('myTag', tagOptions); 当自定义的标签需要要模板与方法时,一般会使用这种方式来注册自定义标签,我们可以在render方法里面处理参数或者属性,然后渲染模板,this.tagCxt对象下,有当前view model的数据供访问
     <div id="result"></div>
    
        <script type="text/x-jsrender" id="tml">
            {{myPersonInfo name age addPrefix=false /}}
        </script>
    
        <script>
            var info = {
                name: 'van',
                age: 20
            };
    
            $.views.tags({
                'myPersonInfo': {
                    render: function () {
                        //这里可以获取到自定义标签里面的属性或者参数
                        //可以使用 this.tagCtx.args, this.tagCtx.props, this.tagCtx.view.data 访问 view model里面的任何数据
    
                        console.log(this.tagCtx);
                        if (this.tagCtx.props.addPrefix) {
    
                            return '<h3>Hello, ' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';
                        } else {
    
                            //使用this.tagCtx.render({name:'lbl'})来渲染定义的模板,并把模板需要的数据传进去
                            return this.tagCtx.render({ name: 'lbl' }) + '<h3>' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';
                        }
                    },
                    template: '<h2>{{:name}}</h2>'
                }
            });
    
            var html = $('#tml').render(info);
            $('#result').append(html);
        </script>

    当然,如果我们不需要模板,那么就只定义一个方法就好了。

     $.views.tags('myPersonInfo', function(){                
                if (this.tagCtx.props.addPrefix) {
                    return '<h3>Hello, ' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';
                }
            });

    当然,也可能你的自定义标签只需要模板,并不需要方法来处理,那么也是没问题的,当然模板里面也是可以访问各种参数、属性的,只是需要使用~tag.tagCtx对象访问。

    <script id="myPersonInfo" type="text/x-jsrender">
            {{myPersonInfo name age=age /}}
        </script>
    
        $.views.tags('myPersonInfo', {
            template: '<h3>{{:~tag.tagCtx.args[0]}}</h3><p>{{:~tag.tagCtx.props.age}}</p>'
        });
    
        //也可以这样
        <script id="myPersonInfo" type="text/x-jsrender">
            {{myPersonInfo name age addPrefix=false}}
                <h3>{{:~tag.tagCtx.args[0]}}</h3>
                <p>no info</p>
            {{/myPersonInfo}}
        </script>
    
        //也可以使用tag.tagCtx.content获取到自定义标签中的内容
        $.views.tags('myPersonInfo', {
            template: '{{if ~tag.tagCtx.props.addPrefix == true}}\
                        <h3>Hello, {{:~tag.tagCtx.args[0]}}</h3>\
                        <p>{{:~tag.tagCtx.props.age}}</p>\
                        {{else tmpl=~tag.tagCtx.content}}\
                        {{:~tag.tagCtx.content}}\
                        {{/if}}'
        });
    
      //或者这样
        <script id="teamTemplate" type="text/x-jsrender">
          <p><b>{{:title}}</b></p>
          <ul>
            {{range members start=1 end=2}} 
              <li>
                {{:name}}
              </li>
            {{/range}}
          </ul> 
        </script>
    
        $.views.tags("range", {
            template: 
                "{{for ~tag.tagCtx.args[0]}}" +
                "{{if #index >= ~tag.tagCtx.props.start && #index <= ~tag.tagCtx.props.end}}" +
                "{{include tmpl=~tag.tagCtx.content/}}" +
                "{{/if}}" +
                "{{/for}}"
        });
    View Code

    当然也可以为某个模板注册私有的自定义标签

      $.views.tags({
          myTag1: ...,
          myTag2: ...
        }, parentTemplate);

    6、使用$.views.settings.debugMode()开启调试模式

    当我们使用jsrender写代码时,难免会报一些错,然后直接在控制台抛出错误异常。但是我们想对错误信息做一些处理,比如直接把异常输出到页面,或者自定义错误信息为字符窜,或者抛出错误的时候,先调用函数处理再抛出错误。jsrender提供了$.views.settings.debugMode()传入不同的参数来改变全局抛出异常的情况。

    1. false 内容不会被渲染并且在控制台抛出异常 (默认)
    2. true 抛出的异常会渲染在页面中,在控制台中没有异常抛出
    3. "string" 字符串会替代错误信息渲染在页面中,在控制台没有异常抛出
    4. function 在异常抛出之前,会先经过传入的方法处理,如果此方法没有return,那么就会把错误信息渲染到页面中,如果有return,那么页面中就会渲染return 的信息
    $.views.settings.debugMode(function(err){
            var errMsg = '';
            if(err){
                errMsg = 'here has error the err is ' + err;
            }
            return errMsg;
        });

    当然,除了为全局处理错误信息之外,也可以使用onError属性为某一个标签定义错误信息,如果你已经在全局设置了处理错误信息的方法,并且传入的参数有返回值(上面提到的3跟4),onError属性是不会起作用的

        {{:address.street onError="Address unavailable"}}
        {{for phones() onError="<em>No phones</em>"}}
        {{:address.street onError=name + " has no address"}}
        {{:address.street onError=~errorMessages(1, name, 'address')}}
        {{myCustomTag ... onError=""}}
    
        $.views.settings.debugMode("this is global err"); //会覆盖上面的onError属性
        or
        $.views.settings.debugMode(function(err){
    
            var errMsg = '';
    
            if(err){
    
                errMsg = 'here has error the err is ' + err;
            }
            return errMsg; //如果return 就会渲染这个,如果不return 就会渲染onError属性的值
        });

    当我们使用render()方法渲染模板的时候,我们想查看某个对象或者某个属性的值,但是并不能在模板中打断点,jsrender提供以下方式在渲染模板的过程中输出对象或者属性的值

    {{dbg expression/}}  tag
    {{dbg: expression}}   convert
    {{:~dbg(expression)}}  helper

    以上的三种方式都会把值渲染在页面,并在控制台中输出值,但是呢,如果值是一个对象,那么就会输出字符串,比如

    JsRender dbg breakpoint: [object Object]

    我们需要看对象里面有什么属性,但是却给我们输出的是字符串,显然不方便调试,所以我们可以重写这个调试标签,让输入值原样输出

    //重写dbg调试模式
        $.views.helpers({
            dbg: function(val){
    
                try {
                    console.log(val);
                    return val;
                }catch (e) {
                    console.log(e);
                }
            }
        });
    
        $.views.converters({
            dbg: function(val){
    
                try {
                    console.log(val);
                    return val;
                }catch (e) {
                    console.log(e);
                }
            }
        });
    
        $.views.tags('dbg', function(val){
    
            try {
                console.log(val);
                return val;
            }catch (e) {
                console.log(e);
            }
        });

    这样重写之后,控制台输出变成这样,就比较方便调试了

    Object {name: "bolin", age: 20}
    参考:https://www.jianshu.com/p/3151d2256410
  • 相关阅读:
    百度地图代码API
    3层下拉列表
    stl+数论——1247D
    数论+乱搞——cf181B
    思维+multiset优化——cf1249E
    线性基思想+贪心——cf1249C
    tarjan求强连通+缩点——cf1248E
    排序+模拟+优先队列——cf1248E
    栈+括号序列+暴力枚举——cf1248D1
    二分+贪心——cf1251D
  • 原文地址:https://www.cnblogs.com/vanblog/p/8676881.html
Copyright © 2011-2022 走看看