vdt.js v0.3.2
Vdt.js
vdt is short for virtual-dom template
Vdt.js
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.js
Features
- 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:parent>
<b:section>
- Easy to use. You can use it with any other js library, such as jQuery. See vdt-todomvc
Install
npm install vdt.js --save
Example
<!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 id="add" value={input} /> input: {input}
<ul>
{/* output users */}
{users.map(function(user, index) {
return <li class="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>
{/* 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 data = {
users: [
{name: 'John', id: '1'},
{name: 'Javey', id: '2'},
{name: 'Tom', id: '3'},
{name: 'Sarah', id: '4'}
],
input: ''
};
var str = document.getElementById('template').innerHTML,
vdt = Vdt(str),
dom = vdt.render(data);
document.body.appendChild(dom);
var input = document.getElementById('add');
input.addEventListener('input', function(e) {
data.input = e.target.value;
vdt.update(data);
});
input.addEventListener('change', function(e) {
data.users.push({name: e.target.value, id: data.users.length});
data.input = '';
vdt.update(data);
});
</script>
</body>
</html>
Custom attributes
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>
Notice
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>
.
Express middleware
Take vdt as a express middleware.
app.use(require('vdt.js').middleware({
src: 'vdt/src/path',
amd: true, // and amd wrapper
force: false, // force compile
autoReturn: true // see api of `Vdt` below
}));
Escape & Unescape
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>
Event
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>
Template Extend
Vdt template can be extended. Use <t:templateFunction>
and <b:block>
directive.
Use <t:templateFunction>
to extend the parent template function. templateFunction
is a function of parent template.
Use <t:block
> to set block which can be filled by child.
Use parent()
to get parent content.
<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 parent = Vdt.compile(document.getElementById('parent').innerHTML);
<t:parent title="child card title">
<b:body>
<div>child body</div>
</b:body>
<b:footer>
{parent()}
<div>child footer</div>
</b:footer>
</t:parent>
</script>
Api
Vdt(source, options)
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
Vdt.compile(source, options)
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
.
template.source
The source code of template function.
The vdt
object
The object returned by Vdt
.
vdt.render(data)
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
vdt.update(data)
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
vdt.data
The data passed to vdt above. So you can modify it directly.
Vdt.parse(source)
Parse JSX template to an ast object
- @param
source
{String} JSX template source - @return {Object} abstract syntax tree object
Vdt.stringify(ast)
Stringify the ast object to hscript string.
- @param
ast
{Object} abstract syntax tree object - @return {String} hscript string with a return expression at end
Vdt.virtualDom
The object exported by virtual-dom module.
Benchmark
See Benchmark
Render(compile every time)
- 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
Update(cache compiled result)
- 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
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago