0.3.2 • Published 10 years ago

vdt.js v0.3.2

Weekly downloads
82
License
-
Repository
-
Last release
10 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

10 years ago

0.3.1

10 years ago

0.3.0

10 years ago

0.2.4

10 years ago

0.2.3

10 years ago

0.2.2

10 years ago

0.2.1

10 years ago

0.2.0

10 years ago

0.1.6

10 years ago

0.1.5

10 years ago

0.1.4

10 years ago

0.1.3

10 years ago

0.1.2

10 years ago

0.1.1

10 years ago

0.1.0

10 years ago

0.0.6

10 years ago

0.0.5

10 years ago

0.0.4

10 years ago

0.0.3

10 years ago

0.0.2

10 years ago

0.0.1

10 years ago