一个基于虚拟DOM的模板引擎,详情请访问:Documents
- 基于virtual-dom,DOM更新速度快
- 能实现前后端模板继承,包含,宏定义等
- 文件大小在gzip压缩后大概13KB(包含浏览器实时编译模块)
- 支持前后端渲染
Vdt会暴露全局变量Vdt
,请到github下载对应的文件,
或者通过bower安装,然后script标签引入
bower install vdt --save
<script type="text/javascript" src="path/to/vdt.js"></script>
使用npm方式安装依赖
npm install vdt --save
var Vdt = require('vdt');
Vdt打包的文件支持通过UMD方式加载
define(['path/to/vdt'], function(Vdt) { });
MIT
vdt is short for virtual-dom template
Vdt
is a template engine based on virtual-dom technology.
It is inspired by React/virtual-dom,
and uses JSX as template syntax.
See TodoMVC implemented by Vdt
See Documents for more information.
- Just the ui. Just the template further more. But more powerful than common template.
- Virtual-dom. Diff update unlike Handlebars/mustache.js.
- Lightweight. Rewrite a compiler instead of jstransform. Discard ES6 syntax sugar and JS analysis, so it's faster.
- Template can be extended.
<t:template>
<b:block>
- Easy to use. You can use it with any other js library, such as jQuery. See vdt-todomvc
npm install vdt --save
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>vdt template engine demo</title>
</head>
<body>
<script type="text/vdt" id="template">
var a = 1, // this is a
showInfo = function(index, name) {
alert('Click ' + index + ' ' + name);
}
<div class="users">
<input value={input} ev-change={add} ev-input={change}/> input: {input}
<ul>
{/* output users */}
{users.map(function(user, index) {
return <li className="user" id={user.id} ev-click={
// use es5's bind or underscore's bind to pass arguments
showInfo.bind(null, index, user.name)
// or function
/*function() {
showInfo(index, user.name);
}*/
}>{index}: {user.name}</li>
})}
</ul>
{/* custom attributes */}
<div attributes={{'data-a': a, input: input}} id={a} ev-dblclick={function() {console.log('Dblclick')}}>this is a({a})</div>
</div>
</script>
<script type="text/javascript" src="../dist/vdt.js"></script>
<script type="text/javascript">
var vdt = Vdt(document.getElementById('template').innerHTML),
model = {
users: [
{name: 'John', id: '1'},
{name: 'Javey', id: '2'},
{name: 'Tom', id: '3'},
{name: 'Sarah', id: '4'}
],
input: '',
add: function(e) {
model.users.push({name: e.target.value, id: model.users.length});
model.input = '';
vdt.update();
},
change: function(e) {
model.input = e.target.value;
vdt.update();
}
};
document.body.appendChild(vdt.render(model));
</script>
</body>
</html>
See vnode.md
You can write template like this to render custom attributes directly.
<div attributes={{'data-a': a, input: input}} id={a}>this is a({a})</div>
-
UseclassName
instead ofclass
in html. -
All html tags must be closed. e.g.<input />
. -
Use
{/* comment */}
instead of<!-- comment -->
. It is just Javascript comment which is wrapped by{}
. -
The last html element will be returned. You must wrap all html in a element. e.g.
<div> <h1>title</h1> <div>body</div> </div>
instead of
<h1>title</h1> <div>body</div>
The second one will return only one element
<div>body</body>
.
Take vdt as a express middleware.
app.use(require('vdt').middleware({
src: 'vdt/src/path',
amd: true, // and amd wrapper
force: false, // force compile
autoReturn: true // see api of `Vdt` below
}));
Any output will be escaped. If you want prevent it, you can do it likes below:
var a = '<h1>title</h1>';
<div>{a}</div> // a will be escaped, -> <div><h1>title</h1></div>
<div innerHTML={a}></div> // a will not be escaped -> <div><h1>title</h1></div>
You can bind event in vdt
template directly by adding ev-event
property, likes below:
<ul>
{/* output users */}
{users.map(function(user, index) {
return <li className="user" id={user.id} ev-click={
// use es5's bind or underscore's bind to pass arguments
showInfo.bind(null, index, user.name)
// or closure
/*function() {
showInfo(index, user.name);
}*/
}>{index}: {user.name}</li>
})}
</ul>
Vdt template can be extended. Use <t:template>
and <b:block>
directive.
Use <t:template>
to extend the parent template function. template
is a function of parent template.
Use <t:block
> to set block which can be filled by child.
Use parent()
to get parent content.
parent
is a keyword for referencing parent block, so don't name template function asparent
.<t:template>
can be nested in<t:block>
;<b:block>
can be nested in<b:block>
.
<script type="text/vdt" id="parent">
<div className="card">
<div className="head">{title}</div>
<b:body>
<div>parent body</div>
</b:body>
<b:footer>
<div>parent footer</div>
</b:footer>
</div>
</script>
<script type="text/vdt" id="child">
// You can also compile it in node, then require it by require.js
var father = Vdt.compile(document.getElementById('parent').innerHTML);
<t:father title="child card title">
<b:body>
<div>child body</div>
</b:body>
<b:footer>
{parent()}
<div>child footer</div>
</b:footer>
</t:father>
</script>
The default delimiter is ['{', '}']
. You can set it by Vdt.setDelimiters(delimiters)
method. For example
- @param
delimiters
{Array}
Vdt.setDelimiters(['{{', '}}']);
Vdt use with
statement to simplify getting data. But it's slow. You can remove it like below.
Vdt.compile(templateString, {noWith: true});
// or
Vdt(templateString, {noWith: true});
Then you can get data like below. use self
, it points to the data that rendered to template.
<div>{self.name}</div>
To simplify writing template, vdt provides some directives as syntax sugar.
{show ? <div>show</div> : undefined}
=>
<div v-if={show}>show</div>
<div>
<div v-if={test === 1}>1</div>
<div v-else-if={test === 2}>2</div>
<div v-else>other</div>
</div>
<ul>
{_.map(data, function(value, key) {
return <li>{value}</li>
})}
</ul>
=>
<ul>
<li v-for={data}>{value}</li>
</ul>
The default key/value
argument's name is 'key/value'. You can change it by using v-for-value/v-for-key
directive.
<ul>
<li v-for={data} v-for-value="item" v-for-key="index">{index}: {item}</li>
</ul>
Compile source
then return a vdt object.
- @param
source
{String|Function} JSX template source or a template function returned byVdt.compile
- @param
options.autoReturn=true
{Object|Boolean} If addreturn
keyword at end or not. The last element of template have to be ahtml tag element
if istrue
. - @return {Object} a vdt object
Compile JSX template source then return a template function which should pass to Vdt
.
The returned function has a property named source. You can use it to pre-process JSX.
- @param
source
{String} JSX template source - @param
options.autoReturn=true
{Object|Boolean} If addreturn
keyword at end or not. The last element of template have to be ahtml tag element
if istrue
. - @return {Function} a template function should pass to
Vdt
.
The source code of template function.
The object returned by Vdt
.
Handle data and return a dom.
- @param
data
{Object} data passed to template @paramthisArg
{Object} the binding of this in template.this
isdata
in template.- @return {Dom} html dom
Handle data and return a html string.
- @param
data
{Object} data passed to template - @return {String} html string
Update the dom using the new data.
- @param
data
{Object} the whole data passed to template. If it is not provided,vdt.data
will be used. - @return {Dom} html dom which has updated
The data passed to vdt above. So you can modify it directly.
Parse JSX template to an ast object
- @param
source
{String} JSX template source - @return {Object} abstract syntax tree object
Stringify the ast object to hscript string.
- @param
ast
{Object} abstract syntax tree object - @return {String} hscript string with a return expression at end
The object exported by virtual-dom module.
See Benchmark
- Vdt.js#render x 5,454 ops/sec ±2.40% (89 runs sampled)
- Lodash#render x 2,390 ops/sec ±3.68% (81 runs sampled)
- Underscore#render x 6,035 ops/sec ±5.86% (81 runs sampled)
- Handlebars#render x 959 ops/sec ±6.16% (77 runs sampled)
- Mustache#render x 4,899 ops/sec ±6.09% (84 runs sampled)
Fastest is Underscore#render
- Vdt.js#update x 14,724 ops/sec ±3.61% (87 runs sampled)
- Lodash#update x 7,734 ops/sec ±2.70% (84 runs sampled)
- Underscore#update x 7,989 ops/sec ±4.52% (89 runs sampled)
- Handlebars#update x 7,200 ops/sec ±2.63% (86 runs sampled)
- Mustache#update x 7,747 ops/sec ±2.40% (96 runs sampled)
Fastest is Vdt.js#update
MIT