0.3.2 • Published 9 years ago

vdt.js v0.3.2

Weekly downloads
82
License
-
Repository
-
Last release
9 years ago

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

demo

<!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

  1. Use className instead of class in html.
  2. All html tags must be closed. e.g. <input />.
  3. Use {/* comment */} instead of <!-- comment -->. It is just Javascript comment which is wrapped by {}.
  4. 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>&lt;h1&gt;title&lt;/h1&gt;</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 by Vdt.compile
  • @param options.autoReturn=true {Object|Boolean} If add return keyword at end or not. The last element of template have to be a html tag element if is true.
  • @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 add return keyword at end or not. The last element of template have to be a html tag element if is true.
  • @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
  • @param thisArg {Object} the binding of this in template. this is data 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

0.3.2

9 years ago

0.3.1

9 years ago

0.3.0

9 years ago

0.2.4

9 years ago

0.2.3

9 years ago

0.2.2

9 years ago

0.2.1

9 years ago

0.2.0

9 years ago

0.1.6

9 years ago

0.1.5

9 years ago

0.1.4

9 years ago

0.1.3

9 years ago

0.1.2

9 years ago

0.1.1

9 years ago

0.1.0

9 years ago

0.0.6

9 years ago

0.0.5

9 years ago

0.0.4

9 years ago

0.0.3

9 years ago

0.0.2

9 years ago

0.0.1

9 years ago