|
6398 | 6398 | </html> |
6399 | 6399 | ``` |
6400 | 6400 |
|
| 6401 | +
|
| 6402 | +## JS Template 模板引擎 |
| 6403 | +
|
| 6404 | +> https://www.jb51.net/article/100095.htm |
| 6405 | +
|
| 6406 | +### 1、特性 |
| 6407 | +
|
| 6408 | +(1)、性能卓越,执行速度通常是 Mustache 与 tmpl 的 20 多倍(性能测试)(2)、支持运行时调试,可精确定位异常模板所在语句(演示) |
| 6409 | +
|
| 6410 | +(3)、对 NodeJS Express 友好支持(4)、安全,默认对输出进行转义、在沙箱中运行编译后的代码(Node版本可以安全执行用户上传的模板) |
| 6411 | +
|
| 6412 | +(5)、支持include语句 |
| 6413 | +
|
| 6414 | +(6)、可在浏览器端实现按路径加载模板(详情) |
| 6415 | +
|
| 6416 | +(7)、支持预编译,可将模板转换成为非常精简的 js 文件 |
| 6417 | +
|
| 6418 | +(8)、模板语句简洁,无需前缀引用数据,有简洁版本与原生语法版本可选 |
| 6419 | +
|
| 6420 | +(9)、支持所有流行的浏览器 |
| 6421 | +
|
| 6422 | +### 2、语法 |
| 6423 | +
|
| 6424 | +(1)、使用 |
| 6425 | +
|
| 6426 | +引用简洁语法的引擎版本,例如:` <script src="./lib/template-web.js"></script> ` |
| 6427 | +
|
| 6428 | +(2)、表达式 |
| 6429 | +
|
| 6430 | +{{ 与 }} 符号包裹起来的语句则为模板的逻辑表达式。 |
| 6431 | +
|
| 6432 | +(3)、输出表达式 |
| 6433 | +
|
| 6434 | +对内容编码输出: {{content}} |
| 6435 | +不编码输出: {{#content}} |
| 6436 | +编码可以防止数据中含有 HTML 字符串,避免引起 XSS 攻击。 |
| 6437 | +
|
| 6438 | +(4)、条件表达式 |
| 6439 | +
|
| 6440 | +```html |
| 6441 | +{{if admin}} |
| 6442 | + <p>admin</p> |
| 6443 | +{{else if code > 0}} |
| 6444 | + <p>master</p> |
| 6445 | +{{else}} |
| 6446 | + <p>error!</p> |
| 6447 | +{{/if}} |
| 6448 | +``` |
| 6449 | +
|
| 6450 | +(5)、遍历表达式 |
| 6451 | +
|
| 6452 | +无论数组或者对象都可以用 each 进行遍历。 |
| 6453 | +
|
| 6454 | +```html |
| 6455 | +{{each list as value index}} |
| 6456 | + <li>{{index}} - {{value.user}}</li> |
| 6457 | +{{/each}} |
| 6458 | +// 亦可以被简写: |
| 6459 | +{{each list}} |
| 6460 | + <li>{{$index}} - {{$value.user}}</li> |
| 6461 | +{{/each}} |
| 6462 | +``` |
| 6463 | +
|
| 6464 | +(6)、模板包含表达式 |
| 6465 | +
|
| 6466 | +用于嵌入子模板。 |
| 6467 | +
|
| 6468 | +`{{include 'template_name'}} ` |
| 6469 | +
|
| 6470 | +子模板默认共享当前数据,亦可以指定数据:`{{include 'template_name' news_list}} ` |
| 6471 | +
|
| 6472 | +(7)、辅助方法 |
| 6473 | +
|
| 6474 | +使用 `template.helper(name, callback) `注册公用辅助方法: |
| 6475 | +
|
| 6476 | +```js |
| 6477 | +template.helper('dateFormat', function (date, format) { |
| 6478 | + // .. |
| 6479 | + return value; |
| 6480 | +}); |
| 6481 | +``` |
| 6482 | +
|
| 6483 | +模板中使用的方式:` {{time | dateFormat:'yyyy-MM-dd hh:mm:ss'}} ` |
| 6484 | +支持传入参数与嵌套使用: `{{time | say:'cd' | ubb | link}} ` |
| 6485 | +
|
| 6486 | +### 3、实例 |
| 6487 | +
|
| 6488 | +```html |
| 6489 | +<!DOCTYPE HTML> |
| 6490 | +<html> |
| 6491 | +<head> |
| 6492 | +<meta charset="UTF-8"> |
| 6493 | +<title>basic-demo</title> |
| 6494 | +<script src="../dist/template.js"></script> |
| 6495 | +</head> |
| 6496 | +<body> |
| 6497 | +<div id="content"></div> |
| 6498 | +<script id="test" type="text/html"> |
| 6499 | +{{if isAdmin}} |
| 6500 | +<h1>{{title}}</h1> |
| 6501 | +<ul> |
| 6502 | + {{each list as value i}} |
| 6503 | + <li>索引 {{i + 1}} :{{value}}</li> |
| 6504 | + {{/each}} |
| 6505 | +</ul> |
| 6506 | +{{/if}} |
| 6507 | +</script> |
| 6508 | +<script> |
| 6509 | +var data = { |
| 6510 | + title: '基本例子', |
| 6511 | + isAdmin: true, |
| 6512 | + list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'] |
| 6513 | +}; |
| 6514 | +var html = template('test', data); |
| 6515 | +document.getElementById('content').innerHTML = html; |
| 6516 | +</script> |
| 6517 | +</body> |
| 6518 | +</html> |
| 6519 | +``` |
| 6520 | +
|
| 6521 | + |
| 6522 | +
|
| 6523 | +
|
| 6524 | +
|
| 6525 | +```html |
| 6526 | +<!DOCTYPE HTML> |
| 6527 | +<html> |
| 6528 | +<head> |
| 6529 | +<meta charset="UTF-8"> |
| 6530 | +<title>no escape-demo</title> |
| 6531 | +<script src="../dist/template.js"></script> |
| 6532 | +</head> |
| 6533 | + |
| 6534 | +<body> |
| 6535 | + <h1>不转义HTML</h1> |
| 6536 | + <div id="content"></div> |
| 6537 | + <script id="test" type="text/html"> |
| 6538 | + <p>不转义:{{#value}}</p> |
| 6539 | + <p>默认转义: {{value}}</p> |
| 6540 | + </script> |
| 6541 | + |
| 6542 | + <script> |
| 6543 | + var data = { |
| 6544 | + value: '<span style="color:#F00">hello world!</span>' |
| 6545 | + }; |
| 6546 | + var html = template('test', data); |
| 6547 | + document.getElementById('content').innerHTML = html; |
| 6548 | + </script> |
| 6549 | +</body> |
| 6550 | +</html> |
| 6551 | +``` |
| 6552 | +
|
| 6553 | + |
| 6554 | +
|
| 6555 | +```html |
| 6556 | +<!DOCTYPE HTML> |
| 6557 | +<html> |
| 6558 | +<head> |
| 6559 | +<meta charset="UTF-8"> |
| 6560 | +<title>include-demo</title> |
| 6561 | +<script src="../dist/template.js"></script> |
| 6562 | +</head> |
| 6563 | + |
| 6564 | +<body> |
| 6565 | +<div id="content"></div> |
| 6566 | +<script id="test" type="text/html"> |
| 6567 | +<h1>{{title}}</h1> |
| 6568 | +{{include 'list'}} |
| 6569 | +</script> |
| 6570 | +<script id="list" type="text/html"> |
| 6571 | +<ul> |
| 6572 | + {{each list as value i}} |
| 6573 | + <li>索引 {{i + 1}} :{{value}}</li> |
| 6574 | + {{/each}} |
| 6575 | +</ul> |
| 6576 | +</script> |
| 6577 | + |
| 6578 | +<script> |
| 6579 | +var data = { |
| 6580 | + title: '嵌入子模板', |
| 6581 | + list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'] |
| 6582 | +}; |
| 6583 | +var html = template('test', data); |
| 6584 | +document.getElementById('content').innerHTML = html; |
| 6585 | +</script> |
| 6586 | +</body> |
| 6587 | +</html> |
| 6588 | +``` |
| 6589 | +
|
| 6590 | + |
| 6591 | +
|
| 6592 | +```html |
| 6593 | +<!DOCTYPE HTML> |
| 6594 | +<html> |
| 6595 | +<head> |
| 6596 | +<meta charset="UTF-8"> |
| 6597 | +<title>helper-demo</title> |
| 6598 | +<script src="../dist/template.js"></script> |
| 6599 | +</head> |
| 6600 | + |
| 6601 | +<body> |
| 6602 | +<h1>辅助方法</h1> |
| 6603 | +<div id="content"></div> |
| 6604 | +<script id="test" type="text/html"> |
| 6605 | +{{time | dateFormat:'yyyy年 MM月 dd日 hh:mm:ss'}} |
| 6606 | +</script> |
| 6607 | + |
| 6608 | +<script> |
| 6609 | +/** |
| 6610 | + * 对日期进行格式化, |
| 6611 | + * @param date 要格式化的日期 |
| 6612 | + * @param format 进行格式化的模式字符串 |
| 6613 | + * 支持的模式字母有: |
| 6614 | + * y:年, |
| 6615 | + * M:年中的月份(1-12), |
| 6616 | + * d:月份中的天(1-31), |
| 6617 | + * h:小时(0-23), |
| 6618 | + * m:分(0-59), |
| 6619 | + * s:秒(0-59), |
| 6620 | + * S:毫秒(0-999), |
| 6621 | + * q:季度(1-4) |
| 6622 | + * @return String |
| 6623 | + * @author yanis.wang |
| 6624 | + * @see http://yaniswang.com/frontend/2013/02/16/dateformat-performance/ |
| 6625 | + */ |
| 6626 | +template.helper('dateFormat', function (date, format) { |
| 6627 | + |
| 6628 | + if (typeof date === "string") { |
| 6629 | + var mts = date.match(/(\/Date(\d+)\/)/); |
| 6630 | + if (mts && mts.length >= 3) { |
| 6631 | + date = parseInt(mts[2]); |
| 6632 | + } |
| 6633 | + } |
| 6634 | + date = new Date(date); |
| 6635 | + if (!date || date.toUTCString() == "Invalid Date") { |
| 6636 | + return ""; |
| 6637 | + } |
| 6638 | + |
| 6639 | + var map = { |
| 6640 | + "M": date.getMonth() + 1, //月份 |
| 6641 | + "d": date.getDate(), //日 |
| 6642 | + "h": date.getHours(), //小时 |
| 6643 | + "m": date.getMinutes(), //分 |
| 6644 | + "s": date.getSeconds(), //秒 |
| 6645 | + "q": Math.floor((date.getMonth() + 3) / 3), //季度 |
| 6646 | + "S": date.getMilliseconds() //毫秒 |
| 6647 | + }; |
| 6648 | + |
6401 | 6649 |
|
| 6650 | + format = format.replace(/([yMdhmsqS])+/g, function(all, t){ |
| 6651 | + var v = map[t]; |
| 6652 | + if(v !== undefined){ |
| 6653 | + if(all.length > 1){ |
| 6654 | + v = '0' + v; |
| 6655 | + v = v.substr(v.length-2); |
| 6656 | + } |
| 6657 | + return v; |
| 6658 | + } |
| 6659 | + else if(t === 'y'){ |
| 6660 | + return (date.getFullYear() + '').substr(4 - all.length); |
| 6661 | + } |
| 6662 | + return all; |
| 6663 | + }); |
| 6664 | + return format; |
| 6665 | +}); |
| 6666 | + |
| 6667 | +// -------- |
| 6668 | + |
| 6669 | +var data = { |
| 6670 | + time: 1408536771253, |
| 6671 | +}; |
| 6672 | +var html = template('test', data); |
| 6673 | +document.getElementById('content').innerHTML = html; |
| 6674 | +</script> |
| 6675 | +</body> |
| 6676 | +</html> |
| 6677 | +``` |
6402 | 6678 |
|
| 6679 | + |
0 commit comments