Coder Social home page Coder Social logo

juicer's Introduction

Juicer 中文文档

当前最新版本: 0.6.14

Juicer 是一个高效、轻量的前端 (Javascript) 模板引擎,使用 Juicer 可以是你的代码实现数据和视图模型的分离(MVC)。除此之外,它还可以在 Node.js 环境中运行。

你可以在遵守 MIT Licence 的前提下随意使用并分发它。Juicer 代码完全开源并托管在 Github 上,如果你在使用的过程中发现什么 Bug 抑或是一些好的建议都欢迎在 Github Issue 上提交。

名字的由来

倘若我们把数据比作新鲜可口的水果,把模板看做是水,Juicer 就是把水果和水榨出我们需要的HTML代码片段的榨汁机。

Juicer 的引入

<script type="text/javascript" src="juicer-min.js></script>

* 使用方法

> 编译模板并根据所给的数据立即渲染出结果.

juicer(tpl, data);

> 仅编译模版暂不渲染,它会返回一个可重用的编译后的函数.

var compiled_tpl = juicer(tpl);

> 根据给定的数据,对之前编译好的模板进行数据渲染.

var compiled_tpl = juicer(tpl);
var html = compiled_tpl.render(data);

> 注册/注销自定义函数(对象),在下边 ${变量} 中会有实例.

juicer.register('function_name', function);
juicer.unregister('function_name');

> 自定义模板语法边界符,下边是 Juicer 默认的边界符。你可以借此解决 Juicer 模板语法同某些后端语言模板语法冲突的情况.

juicer.set({
	'tag::operationOpen': '{@',
	'tag::operationClose': '}',
	'tag::interpolateOpen': '${',
	'tag::interpolateClose': '}',
	'tag::noneencodeOpen': '$${',
	'tag::noneencodeClose': '}',
	'tag::commentOpen': '{#',
	'tag::commentClose': '}'
});

默认参数配置

{
	cache:          true [false],
	strip:          true [false],
	errorhandling:  true [false],
	detection:      true [false]
}

默认配置是 Juicer 推荐的使用方式,如果你使用过程中的确需要更改这些参数,可以这么做:

逐条参数更改:

juicer.set('strip',false);
juicer.set('cache',false);

批量参数更改:

juicer.set({
	'strip': false,
	'cache': false
};

Juicer 默认会对编译后的模板进行缓存,从而避免同一模板多次数据渲染时候重复编译所耗的时间,如无特殊需要,强烈不建议关闭默认参数中的 cache,这么做将会令 Juicer 缓存失效从而降低性能.

* 语法

a. ${变量}

使用 ${} 输出变量值,其中_为对数据源的引用(如${_},常用于数据源为数组的情况)。支持自定义函数(通过自定义函数你可以实现很多有趣的功能,类似 ${data|links} 就可以通过事先定义的自定义函数 links 直接对 data 拼装出<a href=".." alt=".." /> ).

${name}
${name|function}
${name|function, arg1, arg2}

让我们通过一个例子演示一下自定义函数的奇妙用法吧.

var json = {
	links: [
		{href: 'http://juicer.name', alt: 'Juicer'},
		{href: 'http://benben.cc', alt: 'Benben'},
		{href: 'http://ued.taobao.com', alt: 'Taobao UED'}
	]
};

var tpl = [
	'{@each links as item}',
		'${item|links_build} <br />',
	'{@/each}'
].join('');

var links = function(data) {
	return '<a href="' + data.href + '" alt="' + data.alt + '" />';
};

juicer.register('links_build', links); //注册自定义函数 juicer(tpl, json);

上述代码执行后我们会发现结果是这样的:

&lt;a href=&quot;http://juicer.name&quot; alt=&quot;Juicer&quot; <br />
&lt;a href=&quot;http://benben.cc&quot; alt=&quot;Benben&quot; <br />
&lt;a href=&quot;http://ued.taobao.com&quot; alt=&quot;Taobao UED&quot; <br />

可以看得出,结果被转义了,如果我们上边使用 $${item|links} 就会得到我们预期的结果,这就是下边即将提到的避免转义。

转义/避免转义

出于安全角度的考虑,${变量} 在输出之前会对其内容进行转义,如果你不想输出结果被转义,可以使用 $${变量} 来避免这种情况。例如:

var json = {
	value: '&lt;strong&gt;juicer&lt;/strong&gt;'
};

var escape_tpl='${value}';
var unescape_tpl='$${value}';

juicer(escape_tpl, json); //输出 '&lt;strong&gt;juicer&lt;/strong&gt;'
juicer(unescape_tpl, json); //输出 '<strong>juicer</strong>'

b. 循环遍历 {@each} ... {@/each}

如果你需要对数组进行循环遍历的操作,就可以像这样使用 each .

{@each list as item}
	${item.prop}
{@/each}

如果遍历过程中想取得当前的索引值,也很方便.

{@each list as item, index}
	${item.prop}
	${index} //当前索引
{@/each}

c. 判断 {@if} ... {@else if} ... {@else} ... {@/if}

我们也会经常碰到对数据进行逻辑判断的时候.

{@each list as item,index}
	{@if index===3}
		the index is 3, the value is ${item.prop}
	{@else if index === 4}
		the index is 4, the value is ${item.prop}
	{@else}
		the index is not 3, the value is ${item.prop}
	{@/if}
{@/each}

d. 注释 {# 注释内容}

为了后续代码的可维护性和可读性,我们可以在模板中增加注释.

{# 这里是注释内容}

e. 辅助循环 {@each i in range(m, n)}

辅助循环是 Juicer 为你精心设置的一个语法糖,也许你会在某种情境下需要它.

{@each i in range(5, 10)}
	${i}; //输出 5;6;7;8;9;
{@/each}

f. 子模板嵌套 {@include tpl, data}

子模板嵌套可以让你更灵活的组织你的模板代码,除了可以引入在数据中指定的子模板外,当然你也可以通过指定字符串#id使用写在script标签中的模板代码.

HTML代码:

<script type="text/juicer" id="subTpl">
	I'm sub content, ${name}
</script>

Javascript 代码:

var tpl = 'Hi, {@include "#subTpl", subData}, End.';

juicer(tpl, {
	subData: {
		name: 'juicer'
	}
});

//输出 Hi, I'm sub content, juicer, End.
//或者通过数据引入子模板,下述代码也将会有相同的渲染结果:

var tpl = 'Hi, {@include subTpl, subData}, End.';

juicer(tpl, {
	subTpl: "I'm sub content, ${name}",
	subData: {
		name: 'juicer'
	}
});

* 在 Node.js 环境中运行

在命令行中执行:
npm install juicer

在代码中这么引入:
var juicer = require('juicer');
var html = juicer(tpl, data);

在 Express.js 框架中使用

在 Express 2.x 系列版本中:

npm install juicer
var juicer = require('juicer');
app.set('view engine', 'html');
app.register('.html', {
	compile: function(str, options) {
		return juicer.compile(str, options).render;
	}
});

在 Express 3.x 系列版本中:

npm install juicer
var juicer = require('juicer');
var fs = require('fs');
app.set('view engine', 'html');
app.engine('html', function(path, options, fn){
	fs.readFile(path, 'utf8', function(err, str){
		if (err) return fn(err);
		str = juicer(str, options);
		fn(null, str);
	});
});

在 Express 4.x 系列版本中:

var juicerExpressAdapter = require('juicer-express-adapter');
app.set('view engine', 'html');
app.engine('html', juicerExpressAdapter);

在命令行预编译模板文件:

npm install -g juicer
juicer example.juicer.tmpl -f example.js

// type `juicer` after install for more help.
// 全局模式安装 `juicer` 后,在命令行下输入 `juicer` 可以获得更多帮助信息。

为模板引擎设置外部Cache存储:

var juicer = require('juicer');
var LRUCache = require('lru-native');
var cache = new LRUCache({ maxElements: 1000 });

juicer.set('cachestore', cache);

* 一个完整的例子

HTML 代码:

<script id="tpl" type="text/template">
	<ul>
		{@each list as it,index}
			<li>${it.name} (index: ${index})</li>
		{@/each}
		{@each blah as it}
			<li>
				num: ${it.num} <br />
				{@if it.num==3}
					{@each it.inner as it2}
						${it2.time} <br />
					{@/each}
				{@/if}
			</li>
		{@/each}
	</ul>
</script>

Javascript 代码:

var data = {
	list: [
		{name:' guokai', show: true},
		{name:' benben', show: false},
		{name:' dierbaby', show: true}
	],
	blah: [
		{num: 1},
		{num: 2},
		{num: 3, inner:[
			{'time': '15:00'},
			{'time': '16:00'},
			{'time': '17:00'},
			{'time': '18:00'}
		]},
		{num: 4}
	]
};

var tpl = document.getElementById('tpl').innerHTML;
var html = juicer(tpl, data);

juicer's People

Contributors

mejustme avatar paulguo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

juicer's Issues

在Node.js环境里面,添加模版继承的标签

模版继承对于模版而言很重要,希望在服务端能够支持继承语法,比如:
母模版 base.html:

<html>
    {@doLayout}
</html>

子模版:

{@extends 'base.html'}
     <!-- 这里是子模版 -->
{@/extends}

run in ie occur exception : Juicer Compile Exception: Unexpected token

Hello,everyone,

I just use juicer to use my custom function,and in ie it occur exception, and in chrome and firfox is well,

my custom function is in below:
function default_value(self_value, default_val){
if(!self_value || self_value == "undefined") {
return default_val;
}
return self_value;

}
juicer.register('default', default_value);

and the template write like:

<textarea rows="${alt.custom_attr.input_rows}" cols="${alt.custom_attr.input_cols|default,80}" ></textarea>

image

if I delete the "|default,80", it can run well in ie.

doesn't id support custom function?

does anybody know?
Thanks a lot.

else if判断的问题

原来在0.5.0版本中,我提过一个issue:if条件判断时不能识别变量,已在0.5.1中修复,但是这次else if出了这个问题:

{@if isOk}
        1
{@else if var1== var2} 
        2
{@/if}

标签属性被转成小写的问题。

我有一段模板定义:

<script id="resourceConfiguration" type="text/template">
<div id="resourcePropertiesDiv" configurationCode="${_.configurationCode}">
    ......
</div>
</script>

juicer渲染后变成:

<div id="resourcePropertiesDiv" configurationcode="xxx">
    ......
</div>

它把div的configurationCode属性名转成configurationcode小写了?
是我哪里用错了吗,多谢。

关于在juicer直接执行函数

经常会有这个需求,有些数据需要在模版中转换,比如1转成A
String.fromCharCode(${data}+65)或者${String.fromCharCode(data+65)}
我希望直接在模版里面这么用,而不是注册函数,可以吗?

中文字段无法渲染

var obj={名字:'jike'};
var tpl='test juicer${名字}';
juicer(tpl,obj);

result:
Juicer Compile Exception: Cannot read property '0' of null

envrioment: chrome 28,win7
version:0.6.4-stable

循环会污染外部变量

var html = '{@each array as item} ${item} {@/each} ${item}'
var data = {array: [1,2], item: 'a'}
juicer.to_html(html, data)

输出===> " 1 2 2"

预期应该是 "1 2 a"

能否在template里面自定义局部变量?

您好,请问,我能在在模板里面定义局部变量吗?情况如下:

js data:
var json = { person:[{ 0 : { name:'test' ...... } ,1 : { name:'text' .......} }] };

template:
{@each person as p,index}
${p[index].name}
请问我能为p[index]定义一个局部变量吗?
{@/each}

关于循环json 获取不到属性值

遍历json的时候变量的值是空(空字符串)不知道为啥?
var data= {"list":[{name:"A",age:12},{name:"B",age:10},{name:"C",age:14}]}

{@each list as it,index}
${it.name} //这里的值获取不到
{@/each}

twice loop problem!

var data={
list:[
{name:'guokai',show:true},
{name:'benben',show:false},
{name:'dier',show:true}
],
blah:[
{num:1},
{num:2,inner:[
{'time':'15:00'},
{'time':'16:00'}
]},
{num:3,inner:[
{'time':'15:00'},
{'time':'16:00'},
{'time':'16:00'}
]},
{num:4,inner:[
{'time':'15:00'},
{'time':'16:00'},
{'time':'16:00'}
]}
]
};
var tpl=[
'

    ',
    '{@each list as it,k}',
    '
  • ${it.name} (index: ${k})
  • ',
    '{@/each}',
    '{# first level attribute must specify the "data." prefix}',
    '{@each blah as it}',
    '
  • ',
    'num: ${it.num}
    ',
    '{@if it.num==3}',
    '{@each it.inner as it2}',
    '${it2.time}
    ',
    '{@/each}',
    '{@/if}',
    '
  • ',
    '{@/each}',
    '
'
].join('');

console.log(juicer(tpl,data));

output only three items limited by the max number of the second loop,but the first loop have full 4 items?why?

一些优化与建议

现在貌似不支持模板嵌套啊,这个很有用的!还有个人觉得渲染速度方面还有优化空间,可以参考下artTemplate的做法或许可以再提升些渲染速度~~~

foreach bug

var obj = {"proList":prosList,"selPro":defValue};
var proTemp = '{@each proList as item}<li data-value="${item.id}" {@if item.id == selPro}class="sel"{@/if}>${item.prop}{@/each}';

Exception:selPro is not defined

比如我的json里面没有内容,是一个空的数组,我怎么获得这个数组的长度

json代码如下:
var data={ "httop10" : [{"pid":"1", "ftpuser":"tianyi", "domainname":"webabc.com", "starttime":"2013-1-1", "endtime":"2015-1-1", "state":"1"}]};
这个是正常情况下,我可以获得一条结果,但是有的查询条件得到的结果是空的。
var data={ "httop10" : []};
我想在判断如果是空的话,我要显示一句话 “没有查询到结果”,但是没有找到判断这个长度的方法。
{@each httop10 as ht,index}
{@if httop10.length==0} //关键是这句,是不是如果是空的,就不会走each了
没有查询到结果
{@else}
{#这事正常情况下的}
{@/if}
{/each}
起初是认为不走each那里了,我把那一句单独拿到了外面
{@if httop10.length==0}

没有查询到结果 {/if} 这样会输出一个undefined。。。 麻烦告诉一下怎么解决,谢谢了

关于escapehtml优先级的问题

一般的escapehtml作为安全策略,但是大部分情况下使用模板是希望返回html的,例如:

{$item|radio:1}

希望快速的拼接一个radio标签,而且框架的tag功能非常好,完全可以解决过滤功能,例如:
{$username|escape}

似乎修改interpolateOpen, noneencodeOpen 不能解决问题,希望给点指点。

谢谢

辅助循环中的m,n不能使用变量

辅助循环 {@each i in range(m, n)}中,当m或n用变量就会出错,提示“Juicer Compile Exception: Missing catch or finally after try”
代码:
var seat_data={
desks:[
{type:"VIP席",amount:20},
{type:"普通席",amount:60}
]
}
模板:
{@each desks as desk}
{@each i in range(1,desk.amount)}
${i}
{@/each}
{@/each}

if判断boolean类型出错

在0.5.0版本,若foo.isOk是个boolean,if(foo.isOk==true)这样判断是正确的;
但在0.5.1版本,这样写出错,只能这样if(foo.isOk)才正确。

if条件判断时不能识别变量

形如下面这部分代码是正确的:

<script src='juicer-min.js' type='text/javascript'></script>
<script id="tpl" type="text/template">
${first} ${second}
{@if first == second }
    ok
{@/if}
</script>


<script>
function test() {
    var tpl = juicer(document.getElementById('tpl').innerHTML);
    var data = {};
    data['first'] = 102;
    data['second'] = 102;
    html = tpl.render(data);
    alert(html);
}
test();
</script>

但是我将模板中这一行${first} ${second}去掉,就会报second is not defined的错误,同时渲染失败。

关于模板嵌套,不知道是不是有更好的方案

不知道有没有方案把模板嵌套处理与数据填充分离

打个比方,专门有个对象维护模板的嵌套关系,这部分与数据无关,通过这个对象,可以返回一个合并后的模板。
然后 再对模板进行数据填充之类的。

而不是像现在这样,在填充数据的同时处理嵌套,这样好像不是很合理

怎么样在自定义函数中取得所有的参数?

怎么样在自定义函数中取得所有的参数?

比如${ } 中间我想将整个对象传递到一个函数中做判断。
可能比整个更复杂的逻辑,我的意思就是有没有办法传递整个data ={} 进去。
function proc_image(data){
if(data.a=1 &&data.b = 3){
return '123';
}else{
return '4,5,6'
}
}

关于核心算法的一些小建议

希望能用词/语法分析理论实现核心算法……
貌似现在是用regular expr做的。
这样可以,但是性能比较低。

很喜欢这个软件……juicer,名字也很好听
加油!

添加一个定义代码块的功能

虽然juicer支持{@include tpl, data},但是这个有点不太方便,看看能不能添加一个语法糖:
定义一个代码段

{@tpl 'commonTpl'}
<span>备注</span>
{@/tpl}
调用代码段
{@include 'commonTpl'}

添加了这个语法糖,就可以将模板都放在同一个script标签内了。

编译函数juicer不支持ID?

在使用juicer函数进行编译时,不支持ID的方式: var tpl = document.getElementById('tpl').innerHTML ;var compiledTpl = juicer(tpl) ;
这种方式未免太不优雅了吧。BaiduTemplate等模板库都会直接支持ID的方式:var info = baidu.template('list' ,data) ;// list为模板ID,期待后续版本中会加上此特性。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.