首页 > 代码库 > Road to the future——伪MVVM库Q.js

Road to the future——伪MVVM库Q.js

模仿Vuejs的伪MVVM库,下面是使用说明 
项目地址:https://github.com/miniflycn/Q.js

 

相关项目:https://github.com/miniflycn/Ques

一个简单例子

模版:

<a href=http://www.mamicode.com/"javascript:void(0)" q-text="msg"></a>

脚本:

var vm = new Q({    el: ‘#demo‘,    data: {        msg: ‘hello‘    }});

则会展示:

<a href=http://www.mamicode.com/"javascript:void(0)">hello</a>

当使用.data方法修改data时候会触发节点数据修改:

vm.$set(‘msg‘, ‘你好‘);

则会展示:

<a href=http://www.mamicode.com/"javascript:void(0)">你好</a>

TodoMVC例子

我们用Q.js实现了一个TodoMVC的例子: 
https://github.com/miniflycn/Q.js/tree/master/examples/todomvc

相比jQuery的实现,分层较为清晰,而比BackBone的实现要简单。

当然我们与Vuejs的实现非常像,咳咳。

基本概念

directive

告知libaray如何对节点进行操作,遵循Vuejs写法:

<element  prefix-directiveId="[argument:] expression [| filters...]"></element>

简单例子:

<div q-text="message"></div>

这里表示message对应的数据,用text指令进行操作,text指令是在该节点塞入文字。

自定义directive

举一个我们在todoMVC的例子:

<input q-todo-focus="editing" />

则表示editing对应的数据变化时执行todo-focus指令,看看我们todo-focus指令怎么写的:

directives: {    ‘todo-focus‘: function (value) {        // 如果editing的值为false,则不处理        if (!value) {            return;        }        // 为true则,对该节点focus()一下        var el = this.el;        setTimeout(function () {            el.focus();        }, 0);    }}

通用directive

目前只提供了极少的通用directive,未来可拓展

  • show - 显示与否
  • class - 是否添加class
  • value - 改变值
  • text - 插入文本
  • repeat - 重复节点
  • on - 事件绑定
  • model - 双向绑定(只支持input、textarea)
  • vm - 创建子VM

filter

如果设置了filter,则绑定的数据会经过filter才执行对应的directive,这是我们可以在塞入数据前做输出处理,或事件触发前做数据处理。

模版:

<input q-model="msg" q-on="keyup: showMsg | key enter" />

key是其中一个通用filter,基本实现是:

var keyCodes = {        enter    : 13,        tab      : 9,        ‘delete‘ : 46,        up       : 38,        left     : 37,        right    : 39,        down     : 40,        esc      : 27    };/** * A special filter that takes a handler function, * wraps it so it only gets triggered on specific * keypresses. v-on only. * * @param {String} key */function key(handler, key) {    if (!handler) return;    var code = keyCodes[key];    if (!code) {        code = parseInt(key, 10);    }    return function (e) {        if (e.keyCode === code) {            return handler.call(this, e);        }    };}

则,当keyup发生,keyCode为13(即enter)时候,才会触发showMsg方法。

method

特制on指令会调用的方法,例如:上面讲到的showMsg。

设置方法:

var vm = new Q({    el: ‘#demo‘,    data: {        msg: ‘hello‘    },    methods: {        showMsg: function () {            alert(this.msg);        }    }});

则那个input框会在初始化时自动设值为hello,当改变时候msg值也会改变,当按下回车键,则会触发showMsg方法打印值。

data

大部分操作都和对象与数组的操作相同,只有当设置值的时候需要使用.$set方法,因为我们没有defineProperty的支持。

  • 得到一个msg的值:
vm.msg
  • 设置msg的值
vm.$set(‘msg‘, obj);
  • 对于数组可使用大部分数组方法,目前已经支持了:pushpopunshiftshiftindexOfspliceforEachfilter

性能如何

感谢@ouvenzhang提供的测试数据,具体参考https://github.com/miniflycn/Q.js/tree/master/benchmarks

用例Q.jsjQueryNative
单节点html操作OPS82,652 ops/sec ±2.32%46,526 ops/sec ±5.45%1,101,462 ops/sec ±1.06%
多节点html操作OPS23,641 ops/sec ±0.58%4,416 ops/sec ±7.76%33,434 ops/sec ±1.37%
1000个节点repeat渲染操作OPS13.54 ops/sec ±2.32%31.67 ops/sec ±5.45%前一个数据为通常的模版引擎

Road to the future——伪MVVM库Q.js