您的位置:首页 > 其它

Handlebars块级Helpers

2016-07-26 16:16 246 查看

1.Handlebars简单介绍:

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

2.参考文章:

Handlebars官网:http://handlebarsjs.com/

Handlebars中文介绍(王赛):http://www.ghostchina.com/introducing-the-handlebars-js-templating-engine/

Handlebars中文文档 - 块级helpers(译自官方版):https://segmentfault.com/a/1190000000347965

Handlebars.js 中文文档:http://keenwon.com/992.html

js模版引擎handlebars.js实用教程:/article/4847559.html

handlebars玩家指南:http://cnodejs.org/topic/56a2e8b1cd415452622eed2d

com.github.jknack.handlebars.Helper:http://www.programcreek.com/java-api-examples/index.php?api=com.github.jknack.handlebars.Helper

3.块级Helpers使用技巧:

Handlebars内置了
with,
each
,[code]if,unless,
log这5种基本的
Helpers。

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

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

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

<h1>订单列表</h1>
<div class="record">
<table class="order>
<thead>
<tr class="centerTr" >
<th >采购凭证号</th>
<th >公司</th>
<th >供应商编号</th>
<th >项目交货日期</th>
<th >产地</th>
</tr>
</thead>
<tbody>
{{#each _DATA_.orderList}}
<tr>
<td>{{purproofno}}</td>
<td>{{company}}</td>
<td>{{supplierno}}</td>
<td>{{projectdate}}</td>
<td>{{proplace}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>


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

Handlebars.registerHelper 'jsonToStr', (json, options) ->
JSON.stringify(json)

Handlebars.registerHelper 'add', (a,b, options) ->
a + b

Handlebars.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 formatedPrice

Handlebars.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.length

Handlebars.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 0

Handlebars.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的结果:

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<String, Optional<Template>> 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<String, Optional<Template>> initCache(boolean buildCache) {
if (buildCache) {
return CacheBuilder.newBuilder().expireAfterWrite(5,

TimeUnit.MINUTES).build(new CacheLoader<String, Optional<Template>>() {
@Override
public Optional<Template> load(String path) throws Exception {
Template t = null;
try {
t = handlebars.compile(path);
} catch (Exception e) {
log.error("failed to compile template(path={}), cause:

{}",path, e.getMessage());
}
return Optional.fromNullable(t);
}
});
}
return null;
}

public <T> void registerHelper(String name, Helper<T> helper) {
handlebars.registerHelper(name, helper);
}

public String execInline(String templateStr, Map<String, Object> params) {
return execInline(templateStr, params, null);
}

public String execInline(String templateStr, Map<String, Object> params, String

cacheKey) {
try {
if (params == null) {
params = Maps.newHashMap();
}
Template template;
if (caches == null || cacheKey == null) {
template = handlebars.compileInline(templateStr);
} else {
template = caches.getUnchecked("inline/" + cacheKey).orNull();
}
if(template == null){
log.error("failed to exec handlebars' template:{}", templateStr);
return "";
}
return template.apply(params);
} catch (Exception e) {
log.error("exec handlebars' template failed: {},cause:{}", templateStr,

Throwables.getStackTraceAsString(e));
return "";
}

}

@SuppressWarnings("unchecked")
public String execPath(String path, Map<String, Object> params, boolean

isComponent) throws FileNotFoundException {
try {
if (params == null) {
params = Maps.newHashMap();
}

Template template;
if (isComponent) {
if (caches == null) {
template = handlebars.compile("component:" + path);
} else {
template = caches.getUnchecked("component:" + path).orNull();
}
params.put(RenderConstants.COMPONENT_PATH, path);
} else {
if (caches == null) {
template = handlebars.compile(path);
} else {
template = caches.getUnchecked(path).orNull();
}
}

params.put(RenderConstants.USER, UserUtil.getCurrentUser()); //user
params.put(RenderConstants.HREF, configManager.getFrontConfig

().getCurrentHrefs(Setting.getCurrentHost()));
if(template == null){
log.error("failed to exec handlebars' template:path={}", path);
return "";
}
return template.apply(params);

} catch (Exception e) {
Throwables.propagateIfInstanceOf(e, FileNotFoundException.class);
if (e instanceof HandlebarsException) {
Throwables.propagateIfInstanceOf(e.getCause(),

UserNotLoginException.class);
}
log.error("failed to execute handlebars' template(path={}),cause:{} ",
path, Throwables.getStackTraceAsString(e));
}

return "";
}

public String execComponent(final Component component, final Map<String, Object>

context) {
if (!Strings.isNullOrEmpty(component.getService())) {
Object object = null;
try {
object = invoker.invoke(component.getService(), context);
} catch (UserNotLoginException e) {
log.error("user doesn't login.");
if (context.get(RenderConstants.DESIGN_MODE) == null) {
throw e; // 非 DESIGN_MODE 时未登录需要抛出
}
} catch (Exception e) {
log.error("error when invoke component, component: {}", component, e);

context.put(RenderConstants.ERROR, e.getMessage());
}
context.put(RenderConstants.DATA, object);
}
try {
return execPath(component.getPath(), context, true);
} catch (Exception e) {
log.error("failed to execute handlebars' template(path={}),cause:{} ",
component.getPath(), Throwables.getStackTraceAsString(e));
}
return "";
}

}


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

李白准备在黄鹤楼上题诗的时候看了崔颢写的诗,他认为崔颢的诗可以称为是千古绝唱,觉着自己写不出可以超越崔颢的作品,所以慨叹:“眼前有景道不得,崔颢题诗在上头”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: