博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Handlebars块级Helpers
阅读量:5245 次
发布时间:2019-06-14

本文共 24731 字,大约阅读时间需要 82 分钟。

1.Handlebars简单介绍:

     Handlebars是JavaScript一个语义模板库,通过对view和data的分离来快速构建Web模板。它采用"Logic-less template"(无逻辑模版)的思路,在加载时被预编译,而不是到了客户端执行到代码时再去编译, 这样可以保证模板加载和运行的速度。Handlebars兼容Mustache,你可以在Handlebars中导入Mustache模板。

2.参考文章:

    Handlebars官网:

    Handlebars中文介绍(王赛):

    Handlebars中文文档 - 块级helpers(译自官方版):

    Handlebars.js 中文文档:

    js模版引擎handlebars.js实用教程:

    handlebars玩家指南:

    com.github.jknack.handlebars.Helper:

 

3.块级Helpers使用技巧:

   Handlebars内置了with,eachif,unless,log这5种基本的Helpers。

   if标签只能判断true或false,不能执行一些复杂的运算逻辑。

   这些基本的Helpers并不能满足我们所有的需求,因此需要自定义一些辅助Helpers。

   ① 基本Helpers—each使用示例:orderList.hbs

订单列表

{
{#each _DATA_.orderList}}
{
{/each}}
采购凭证号 公司 供应商编号 项目交货日期 产地
{
{purproofno}}
{
{company}}
{
{supplierno}}
{
{projectdate}}
{
{proplace}}

   ② 自定义Helpers使用示例:handlebars.coffee

Handlebars.registerHelper 'jsonToStr', (json, options) ->  JSON.stringify(json)Handlebars.registerHelper 'add', (a,b, options) ->  a + bHandlebars.registerHelper "formatPrice", (price, type, options) ->  return if not price?  if type is 1    formatedPrice = (price / 100)    roundedPrice = parseInt(price / 100)  else    formatedPrice = (price / 100).toFixed(2)    roundedPrice = parseInt(price / 100).toFixed(2)  if `formatePrice == roundedPrice` then roundedPrice else formatedPriceHandlebars.registerHelper "formatDate", (date, type, options) ->  return unless date  switch type    when "gmt" then moment(date).format("EEE MMM dd HH:mm:ss Z yyyy")    when "day" then moment(date).format("YYYY-MM-DD")    when "minute" then moment(date).format("YYYY-MM-DD HH:mm")    else moment(date).format("YYYY-MM-DD HH:mm:ss")Handlebars.registerHelper "lt", (a, b, options) ->  if a < b    options.fn(this)  else    options.inverse(this)Handlebars.registerHelper "gt", (a, b, options) ->  if a > b    options.fn(this)  else    options.inverse(this)Handlebars.registerHelper 'of', (a, b, options) ->  values = if _.isArray b then b else b.split(",")  if _.contains(values, a.toString()) or _.contains values, a    options.fn(this)  else    options.inverse(this)Handlebars.registerHelper 'length', (a, options) ->  length = a.lengthHandlebars.registerHelper "isArray", (a, options) ->  if _.isArray a    options.fn(this)  else    options.inverse(this)Handlebars.registerHelper "between", (a, b, c, options) ->  if a >= b and a <= c    options.fn(this)  else    options.inverse(this)Handlebars.registerHelper "multiple", (a, b, c, options) ->  if c isnt 0 then a * b / c else 0Handlebars.registerHelper "contain", (a, b, options) ->  return options.inverse @ if a is undefined or b is undefined  array = if _.isArray a then a else a.toString().split(",")  if _.contains a, b then options.fn @ else options.inverse @Handlebars.registerHelper "match", (a, b, options) ->  return options.inverse @ if a is undefined or b is undefined  if new RegExp(a).exec(b) is null then options.inverse @ else options.fn @Handlebars.registerHelper "isOdd", (a, b, options) ->  if a % b == 1    options.fn(this)  else    options.inverse(this)

   handlebars.coffee编译成handlebarsApp.js的结果:

Handlebars.registerHelper('jsonToStr', function(json, options) {    return JSON.stringify(json);  });  Handlebars.registerHelper('add', function(a, b, options) {    return a + b;  });  Handlebars.registerHelper("formatPrice", function(price, type, options) {    var formatedPrice, roundedPrice;    if (price == null) {      return;    }    if (type === 1) {      formatedPrice = price / 100;      roundedPrice = parseInt(price / 100);    } else {      formatedPrice = (price / 100).toFixed(2);      roundedPrice = parseInt(price / 100).toFixed(2);    }    if (formatedPrice == roundedPrice) {      return roundedPrice;    } else {      return formatedPrice;    }  });  Handlebars.registerHelper("formatDate", function(date, type, options) {    if (!date) {      return;    }    switch (type) {      case "gmt":        return moment(date).format("EEE MMM dd HH:mm:ss Z yyyy");      case "day":        return moment(date).format("YYYY-MM-DD");      case "minute":        return moment(date).format("YYYY-MM-DD HH:mm");      default:        return moment(date).format("YYYY-MM-DD HH:mm:ss");    }  });  Handlebars.registerHelper("lt", function(a, b, options) {    if (a < b) {      return options.fn(this);    } else {      return options.inverse(this);    }  });  Handlebars.registerHelper("gt", function(a, b, options) {    if (a > b) {      return options.fn(this);    } else {      return options.inverse(this);    }  });  Handlebars.registerHelper('of', function(a, b, options) {    var values;    values = _.isArray(b) ? b : b.split(",");    if (_.contains(values, a.toString()) || _.contains(values, a)) {      return options.fn(this);    } else {      return options.inverse(this);    }  });  Handlebars.registerHelper('length', function(a, options) {    var length;    return length = a.length;  });  Handlebars.registerHelper("isArray", function(a, options) {    if (_.isArray(a)) {      return options.fn(this);    } else {      return options.inverse(this);    }  });  Handlebars.registerHelper("between", function(a, b, c, options) {    if (a >= b && a <= c) {      return options.fn(this);    } else {      return options.inverse(this);    }  });  Handlebars.registerHelper("multiple", function(a, b, c, options) {    if (c !== 0) {      return a * b / c;    } else {      return 0;    }  });  Handlebars.registerHelper("contain", function(a, b, options) {    var array;    if (a === void 0 || b === void 0) {      return options.inverse(this);    }    array = _.isArray(a) ? a : a.toString().split(",");    if (_.contains(a, b)) {      return options.fn(this);    } else {      return options.inverse(this);    }  });  Handlebars.registerHelper("match", function(a, b, options) {    if (a === void 0 || b === void 0) {      return options.inverse(this);    }    if (new RegExp(a).exec(b) === null) {      return options.inverse(this);    } else {      return options.fn(this);    }  });  Handlebars.registerHelper("isOdd", function(a, b, options) {    if (a % b === 1) {      return options.fn(this);    } else {      return options.inverse(this);    }  });
View Code

 Spring MVC框架中引入handlebars插件:

  Maven配置:handlebars和handlebars-springmvc。

com.github.jknack
handlebars
4.0.5
com.github.jknack
handlebars-springmvc
4.0.5

   在Spring MVC配置文件servlet-context.xml中添加handlebars视图解析器配置:

    Controller中实现代码:

package com.ouc.handlebars.controller;import java.util.HashMap;import java.util.Map;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HandlebarsController {    @RequestMapping(value = "/testHandlebars", method = RequestMethod.GET)    public ModelAndView helloWorld() {          Map
map = new HashMap
(); map.put("helloWorld", "Hello World!"); return new ModelAndView("helloWorld", map); } }

   前端helloWorld.html文件:

    
Hello World
{
{helloWorld}}

 ④ 自定义Helpers后台实现:OucHandlebarHelpers.java

package ouc.handlebars.web.helpers;import com.github.jknack.handlebars.Helper;import com.github.jknack.handlebars.Options;import com.google.common.base.MoreObjects;import com.google.common.base.Objects;import ouc.handlebars.common.utils.MapBuilder;import ouc.handlebars.common.utils.NumberUtils;import ouc.handlebars.common.utils.Splitters;import ouc.handlebars.pampas.engine.handlebars.HandlebarsEngine;import org.joda.time.DateTime;import org.joda.time.Days;import org.joda.time.Hours;import org.joda.time.Minutes;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import java.io.IOException;import java.text.DecimalFormat;import java.util.Collection;import java.util.Date;import java.util.List;import java.util.Map;@Componentpublic class OucHandlebarHelpers {    @Autowired    private HandlebarsEngine handlebarEngine;    @PostConstruct    public void init() {        handlebarEngine.registerHelper("isEmpty", new Helper() {            @Override            public CharSequence apply(Object obj, Options options) throws IOException {                if (obj == null || obj.equals("")) {                    return options.fn();                } else {                    return options.inverse();                }            }        });        //此标签相当于 and 连接的if判断        handlebarEngine.registerHelper("multipleEquals", new Helper() {            @Override            public CharSequence apply(Object source, Options options) throws IOException {                CharSequence ch=options.fn();                CharSequence ch2=options.inverse();                String obj1=String.valueOf(source);                Object[] other=options.params;                if(!Objects.equal(obj1,String.valueOf(other[0]))){                    return ch2;                }                for (int i = 1; i < other.length; i+=2) {                    if(!Objects.equal(String.valueOf(other[i]),String.valueOf(other[i+1]))){                        return ch2;                    }                }                return ch;            }        });        handlebarEngine.registerHelper("get", new Helper() {            @Override            public CharSequence apply(Object context, Options options) throws IOException {                Object collections;                Object param = options.param(0);                if (context instanceof List || context instanceof Map) {                    collections = context;                }                else {                    collections = Splitters.COMMA.splitToList(String.valueOf(context));                }                if (param == null) {                    return null;                }                if(collections instanceof List){                    return ((List)collections).get(Integer.valueOf(param.toString())).toString();                }                else{                    return ((Map)collections).get(param).toString();                }            }        });        handlebarEngine.registerHelper("contain", new Helper() {            @Override            public CharSequence apply(Object context, Options options) throws IOException {                Object collections;                Object param = options.param(0);                if (context instanceof Collection || context instanceof Map ) {                    collections = context;                }                else{                    collections = Splitters.COMMA.splitToList(String.valueOf(context));                }                if (param == null) {                    return options.fn();                }                if(collections instanceof Collection){                    if(((Collection)collections).contains(param)){                        return options.fn();                    }                    else{                        return options.inverse();                    }                }                else {                    Map map = (Map)collections;                    String check = options.param(1, "ALL");                    if("key".equalsIgnoreCase(check)){                        if(map.keySet().contains(param)){                            return options.fn();                        }                        else{                            return options.inverse();                        }                    }                    else if("value".equalsIgnoreCase(check)){                        if(map.values().contains(param)){                            return options.fn();                        }                        else{                            return options.inverse();                        }                    }                    else{                        if(map.keySet().contains(param) || map.values().contains(param)){                            return options.fn();                        }                        else{                            return options.inverse();                        }                    }                }            }        });        handlebarEngine.registerHelper("containAny", new Helper() {            @Override            public CharSequence apply(Object context, Options options) throws IOException {                Object collections;                if (context instanceof Collection || context instanceof Map) {                    collections = context;                } else {                    collections = Splitters.COMMA.splitToList(String.valueOf(context));                }                if (options.params == null || options.params.length == 0) {                    return options.fn();                }                if(collections instanceof Collection){                    for (Object param : options.params) {                        for (String p : Splitters.COMMA.splitToList((String)param)) {                            if (((Collection)collections).contains(p)) {                                return options.fn();                            }                        }                    }                    return options.inverse();                } else {                    Map map = (Map)collections;                    for (Object param : options.params) {                        for (String p : Splitters.COMMA.splitToList((String) param)) {                            if (map.keySet().contains(p) || map.values().contains(p)) {                                return options.fn();                            }                        }                    }                    return options.inverse();                }            }        });        /**         *         * 传参 a, b, c         * 然后a是一个"2015-08-12"或者''2015-08-12 12:00:00"         * b的值可以是"dayStart",''now","dayEnd","2015-08-15",''2015-08-15 12:00:00"中的一个         * 如果b是dayStart, a就和当天的0点0分比较         * 如果b是now, a就和现在时间比较         * 如果b是dayEnd, a就和第二天的0点0分比较         * 如果b是一个date,a就和b比较         * 第三个参数:         * 设置时间的比较级别:s:秒,m:分,h:小时,d:天         */        handlebarEngine.registerHelper("comDate", new Helper() { @Override public CharSequence apply(Object context, Options options) throws IOException { //获取参数 Object param2 = options.param(0); //默认按照秒比较时间 String comType = MoreObjects.firstNonNull((String) options.param(1), "s"); if(context == null || param2 == null){ return options.fn(); }else{ Date comTime1 = new DateTime(context).toDate();//Date)param1; String param = (String)param2; Date comTime2; if(Objects.equal(param , "dayStart")){ //compare1与当天的0点0分比较 comTime2 = DateTime.now().withTime(0 , 0, 0, 0).toDate(); }else if(Objects.equal(param , "now")){ //compare1就和现在时间比较 comTime2 = DateTime.now().toDate(); }else if(Objects.equal(param , "dayEnd")){ //compare1就和第二天的0点0分比较 comTime2 = DateTime.now().plusDays(1).withTime(0 , 0, 0, 0).toDate(); }else{ //compare1就和compare2比较 comTime2 = DateTime.parse(param).toDate(); } if(compareTime(comTime1 , comTime2 , comType)){ return options.inverse(); }else{ return options.fn(); } } } }); /** * 格式化金钱 第一个参数格式化到得金额,第二个是保留小数的位数,第三个是传值为空时返回 * 什么数据,E-empty string(默认),Z-zero * { {formatPrice 变量名 "W" 2 E}} */ handlebarEngine.registerHelper("formatPrice", new Helper
() { Map
sdfMap = MapBuilder.
of().put( "W", 1000000, "Q", 100000, "B", 10000, "Y", 100 ).map(); @Override public CharSequence apply(Number price, Options options) throws IOException { String defaultValue = "E"; if (options.params != null && options.params.length ==3) { defaultValue = options.param(2).toString(); } if (price == null) return defValue(defaultValue); if (options.params == null || options.params.length == 0){ return NumberUtils.formatPrice(price); } else if( options.params.length == 1){ Object param1 = options.param(0); int divisor = sdfMap.get(param1.toString().toUpperCase()) == null?1:sdfMap.get(param1.toString().toUpperCase()); return getDecimalFormat(2).format(price.doubleValue()/divisor); } else if (options.params.length == 2 || options.params.length ==3 ){ Object param1 = options.param(0); Object param2 = options.param(1); int divisor = sdfMap.get(param1.toString().toUpperCase()) == null?1:sdfMap.get(param1.toString().toUpperCase()); return getDecimalFormat(Integer.valueOf(param2.toString())).format(price.doubleValue() / divisor); } return ""; } }); /** * Usage:
{ {formatDecimal 10101.2 2}} -> *
10,101.20 * 第一个参数是传入的数,第二是保留小数位 * 默认不保留小数位 */ handlebarEngine.registerHelper("formatDecimal", new Helper
() { @Override public CharSequence apply(Number number, Options options) throws IOException { if (number == null) { return "0"; } DecimalFormat df; if (options.params == null || options.params.length == 0) { df = getDecimalFormat(0); } else { df = getDecimalFormat(Integer.valueOf(options.params[0].toString())); } return df.format(number.doubleValue()); } }); } private String defValue(String defaultValue) { if (defaultValue.toUpperCase().equals("E")) { return ""; } if (defaultValue.toUpperCase().equals("Z")) { return "0"; } return ""; } private DecimalFormat getDecimalFormat(Integer digits){ DecimalFormat decimalFormat = new DecimalFormat(); Integer fractionDigits = digits == null? 2:digits; decimalFormat.setMaximumFractionDigits(fractionDigits); decimalFormat.setMinimumFractionDigits(fractionDigits); return decimalFormat; } /** * 比较开始时间以及结束时间之间的大小(按照比较级别) * @param startTime 开始时间 * @param endTime 结束时间 * @param comType 比较级别 * @return Boolean * 返回是否大于(true:大于, false:小于) */ private Boolean compareTime(Date startTime , Date endTime, String comType){ Boolean result = false; if(Objects.equal(comType , "s")){ //按照秒比较 result = startTime.after(endTime); }else if(Objects.equal(comType , "m")){ //按照分钟比较 result = Minutes.minutesBetween(new DateTime(startTime), new DateTime(endTime)).getMinutes() > 0; }else if(Objects.equal(comType , "h")){ //按照小时比较 result = Hours.hoursBetween(new DateTime(startTime), new DateTime(endTime)).getHours() > 0; }else if(Objects.equal(comType , "d")){ //按照天比较 result = Days.daysBetween(new DateTime(startTime), new DateTime(endTime)).getDays() > 0; } return result; }}
View Code

  ⑤ HandlebarsEngine.java

package ouc.handlebars.pampas.engine.handlebars;     import com.github.jknack.handlebars.Handlebars;  import com.github.jknack.handlebars.HandlebarsException;  import com.github.jknack.handlebars.Helper;  import com.github.jknack.handlebars.Template;  import com.github.jknack.handlebars.io.TemplateLoader;  import com.google.common.base.Optional;  import com.google.common.base.Strings;  import com.google.common.base.Throwables;  import com.google.common.cache.CacheBuilder;  import com.google.common.cache.CacheLoader;  import com.google.common.cache.LoadingCache;  import com.google.common.collect.Maps;  import ouc.handlebars.pampas.common.UserNotLoginException;  import ouc.handlebars.pampas.common.UserUtil;  import ouc.handlebars.pampas.engine.RenderConstants;  import ouc.handlebars.pampas.engine.Setting;  import ouc.handlebars.pampas.engine.config.ConfigManager;  import ouc.handlebars.pampas.engine.config.model.Component;  import ouc.handlebars.pampas.engine.mapping.Invoker;  import lombok.extern.slf4j.Slf4j;  import org.springframework.beans.factory.annotation.Autowired;     import javax.servlet.ServletContext;  import java.io.FileNotFoundException;  import java.util.Map;  import java.util.concurrent.TimeUnit;     /**   * Author: Wu Ping   */ @org.springframework.stereotype.Component  @Slf4j public class HandlebarsEngine {         private Handlebars handlebars;         private Invoker invoker;         private final LoadingCache
> caches; private ConfigManager configManager; @Autowired public HandlebarsEngine(Invoker invoker, Setting setting, ConfigManager configManager, ServletContext servletContext) { this.invoker = invoker; TemplateLoader templateLoader = new GreatTemplateLoader(servletContext, "/views", ".hbs"); this.handlebars = new Handlebars(templateLoader); this.caches = initCache(!setting.isDevMode()); this.configManager = configManager; } private LoadingCache
> initCache(boolean buildCache) { if (buildCache) { return CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(new CacheLoader
>() { @Override public Optional
View Code

   整个块级Helpers的介绍基本就到这里了,前面介绍handlebars的文章都不错。

   李白准备在黄鹤楼上题诗的时候看了崔颢写的诗,他认为崔颢的诗可以称为是千古绝唱,觉着自己写不出可以超越崔颢的作品,所以慨叹:“眼前有景道不得,崔颢题诗在上头”。

转载于:https://www.cnblogs.com/wp5719/p/5707895.html

你可能感兴趣的文章
【转】代码中特殊的注释技术——TODO、FIXME和XXX的用处
查看>>
php提交表单校验例子
查看>>
man查看帮助命令
查看>>
【SVM】libsvm-python
查看>>
mysql 修改已存在的表增加ID属性为auto_increment自动增长
查看>>
sgu 109 Magic of David Copperfield II
查看>>
C++循环单链表删除连续相邻重复值
查看>>
IIS 7.5 + PHP-5.6.3 + mysql-5.6.21.1(转载)
查看>>
渣渣小本求职复习之路每天一博客系列——Java基础(3)
查看>>
C#调用WIN32 的API函数--USER32.DLL
查看>>
ListView下拉刷新实现
查看>>
Jmeter接口压力测试,Java.net.BindException: Address already in use: connect
查看>>
【7集iCore3基础视频】7-4 iCore3连接示意图
查看>>
ASP.NET使网页弹出窗口不再困难
查看>>
Leetcode Balanced Binary Tree
查看>>
Day1:Spring-IoC、DI
查看>>
Leetcode 92. Reverse Linked List II
查看>>
TensorFlow2-维度变换
查看>>
Redux源码分析之createStore
查看>>
POJ 2060 最小路径覆盖
查看>>