Vdt.js 1.3 发布,基于虚拟 DOM 的前端模板引擎

来源: 投稿
作者: JaveyZ
2018-08-16 15:40:00

Vdt是一个基于虚拟DOM技术的模板引擎,具有如下特性:

  • 基于虚拟DOM,更新速度快

  • 支持模板继承,包含,宏定义等功能

  • 文件大小在gzip压缩后大概13KB(包含浏览器实时编译模块)

  • 支持前后端渲染

基准测试结果:

Benchmark

v1.3版本带来了以下新特性,发布日志

  1. add: 对于组件可以双向绑定任意属性,而非仅仅只是value属性 Javey/Intact#7

  2. add: 更详细的报错信息,可以标示出具体的错误位置 #9

  3. add: 支持同一事件绑定多次回调函数,可以在v-model占用了事件属性后,再次绑定该事件属性,详见双向绑定(v-model) Javey/Intact#9

  4. add: 新增虚拟标签template用于包裹多个元素,template只会渲染子元素,自身不会被渲染,详见模板语法 template #10

  5. add: 支持带参数的block,详见模板继承 带参数的block #8

  6. add: 模板编译后的代码进行了美化,方便调试

  7. change: 现在skipWhitespace也会去掉标签和插值分隔符之间的空白字符 #11

报错信息

之前vdt模板编译出错时,报错信息不够准确,给排查问题造成了很大的困扰。改进后的报错信息,可以像babel那样指定到具体的行和列,并打印出代码片段,例如:

ERROR in ./components/checkbox/index.vdt
Module build failed: Error: Unclosed tag: </span> (19:6)
> 19 |     <span class="k-wrapper">
     |      ^

双向绑定组件的任意属性

对于组件Intact,之前只能通过v-model双向绑定value属性,现在可以绑定任意属性了,用法如下:

<Pagination v-model="page" v-model:limit="size" />

绑定对象的子属性也是可以的

<Component v-model:data.age="age" />

同一事件绑定多个函数

新版支持同一个事件,绑定多个回调函数,注意不是传入数组,而是书写多次该事件属性,例如:

<div ev-click={callbackA} ev-click={callbackB}>click</div>

上例中,当点击div时,callbackAcallbackB会依次执行。

大多数情况下我们无需给同一事件绑定多个事件回调函数,但是由于v-model语法糖的存在,它的编译结果会占用一个事件属性。有了该特性,我们依然可以再次添加同名的事件属性,例如:

<input v-model="data" ev-input={callback} />

它等价于(以下并非真实编译结果)

<input value={data} ev-input={(e) => data = e.target.value} ev-input={callback} />

此时自定义的callback回调函数,也会在input事件触发时执行

template标签

template是一个伪元素,它只会渲染子元素,自身不会被渲染成任何内容。这在我们结合v-forv-if等指令,来渲染和判读多个元素时提供了便利。

<dl>
    <template v-for={list}>
        <dt>{value.name}</dt>
        <dd>{value.age}</dd>
    </template>
</dl>
{
    "list": [
        {"name": "Javey", "age": 18},
        {"name": "Tom", "age": 20}
    ]
}

渲染结果如下:

<dl>
    <dt>Javey</dt>
    <dd>18</dd>
    <dt>Tom</dt>
    <dd>20</dd>
</dl>

带参数的block

block可以传递参数,我们可以在父模板中传递参数给子模板,子模板中接受参数后,可以根据不同的数据渲染不同的结果。这在v-for渲染中很有用,我们可以动态每一次渲染的结果。这类似vue中的slot-scope,不同的是:和所有的block一样,我们可以通过parent()引用父模板中定义的内容。

使用方法如下:

  1. 首先我们需要在父模板中给block指定实参,通过args属性指定,该属性值是一个数组

  2. 然后在子模板中给block指定形参,通过params属性指定,该属性值是一个字符串

// @file ./list.vdt
<ul>
    <li v-for={data}>
        <b:item args={[value, key]}>{value.name}</b:item>
    </li>
</ul>
// @file ./child.vdt
var list = require('./list.vdt');

<t:list data={[
    {name: 'Javey', age: 18},
    {name: 'Tom', age: 20}
]}>
    <b:item params="item, index">
        {index + 1}: {parent()}, {item.age}
    </b:item>
</t:list>

渲染结果如下:

<ul>
    <li>1: Javey, 18</li>
    <li>2: Tom, 20</li>
</ul>

上例中,父模板的item block通过args传入value key当做实参,子模板通过parmas定义形参。可以看到,我们依然可以通过parent()访问到父模板中定义的内容

展开阅读全文
点击加入讨论🔥(5) 发布并加入讨论🔥
5 评论
5 收藏
分享
返回顶部
顶部