IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    observejs改善组件编程体验

    TAT.dnt发表于 2015-05-17 11:01:27
    love 0

    传送门

    observejs:https://github.com/kmdjs/observejs
    本文演示:http://kmdjs.github.io/observejs/list/
    本文代码:https://github.com/kmdjs/observejs/tree/master/example/list

    写在前面

    javascript的编程体验一直被改善,从未停止过。从最早的Jscex(现在的windjs),改善异步编程体验。如今ES6的Generator改善异步编程体验。还有类似的seajs、requirejs提供极致的模块化开发体验;五花八门的Class.js改善面向对象编程体验;kmdjs同时改善模块化编程、面向对象编程和构建体验;各式各样的template.js改善数据->标记的体验。
    所有的改善,使代码更直观、友好,使程序易维护、可扩展。

    最近使用observejs开发组件,发现有几大优点:

    – Dom操作几乎绝迹
    – 专注于数据操作
    – 视图全自动更新
    – 性能棒棒的
    – 仅一行代码搞定上面四点

    本文使用世界上最简单的List组件作为例子,大家通过该例子感受一下observejs组件开发改善之处。

    组件代码

    var List = function (option) {
        this.option = option;
        this.data = option.data;
        this.parent = document.querySelector(this.option.renderTo);
        this.tpl =
            '
    <%=typeof width === "number"?width+"px":width%>;" >' + ' <% for ( var i = 0, len = data.length; i < len; i++) { %>' + '<% var item = data[i]; %>' + '<%=item.active ? "active" : ""%> <%=item.disabled ? "disabled" : ""%>" href="<%=item.href%>" target="<%=item.target?item.target:""%>"><%=item.text%><\/a>' + '<% } %>' + '<\/div>'; this.render(); //list.render建议使用debounce来控制执行频率提高性能,或者和react一样在下次执行requestAnimFrame的时候更新 observe(this, "option", this._debounce(this.render, 200)); } List.prototype = { render: function () { if (this.node) this.parent.removeChild(this.node); this.parent.innerHTML += this._tpl(this.tpl, this.option); this.node = this.parent.lastChild; }, clear:function(){ this.data.size(0); }, remove:function(index){ this.data.splice(index,1); }, add:function(item){ this.data.push(item); }, edit:function(index,item){ this.data[index]=item; }, disable:function(index){ this.data[index].disabled = true; }, _tpl: function (str, data) { var tmpl = 'var __p=[];' + 'with(obj||{}){__p.push(\'' + str.replace(/\\/g, '\\\\') .replace(/'/g, '\\\'') .replace(/<%=([\s\S]+?)%>/g, function (match, code) { return '\',' + code.replace(/\\'/, '\'') + ',\''; }) .replace(/<%([\s\S]+?)%>/g, function (match, code) { return '\');' + code.replace(/\\'/, '\'') .replace(/[\r\n\t]/g, ' ') + '__p.push(\''; }) .replace(/\r/g, '\\r') .replace(/\n/g, '\\n') .replace(/\t/g, '\\t') + '\');}return __p.join("");', func = new Function('obj', tmpl); return data ? func(data) : func; }, _debounce: function (func, wait, immediate) { var timeout; return function () { var context = this, args = arguments; var later = function () { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }, }

    ps:模版引擎来自GMU,当然你可以使用任何你喜欢的额模版引擎

    组件使用

    var list = new List({
        data: [
            { text: "天下太贰", disabled: true, active: true },
            { text: "魔兽争霸", href: "##", target: "_blank" },
            { text: "魔兽世界" },
            { text: "坦克世界" },
            { text: "超级玛丽", disabled: true }
        ],
        width: 150,
        renderTo: "body"
    })
    list.edit(1,{text:"haha"})
    list.add({ text: "aaaa" });
    list.remove(2, 1);
    list.disable(2);
    list.remove(1);
    //操作数据等于操作dom
    list.data[0].text="aaaaaaa";

    组件分析

    其中仅需要一行

    observe(this, "option", this._debounce(this.render, 100));

    就可以实现option的监听,option包含组件的配置,以及数据,数据的变换都能够通知render方法的调用。

    可以看到render方法摧毁了整个dom,然后根据数据重新渲染dom。所以控制render的执行频率变得尤其重要。

    如果数据变化频繁,render方法调用频繁,从而降低性能,所以,可以看到上面使用debounce控制render执行的频率。

    如果不使用debounce,也有第二种方案控制render频率。该方案和react一样,在requestAnimateFrame下次循环的时候去check组件是否要re-render,需要的话就重新渲染。如果一个页面有一百个组件,都统一在requestAnimateFrame循环中check是否re-render。

    可以看到,只有render方法里有dom操作。clear、remove、add、edit、disable都只关心数据,数据变了自动会通知到render。

    改善的地方在哪里?分两处地方:

    1.组件内部代码,内部的增删改查都只关注数据就行

    2.组件使用代码,操作数据等同于操作dom。当然如果不使用赋值又没有observejs的情况下可以使用方法调用的方式,使得一行代码什么都能干,但是如果属性太多,你得定义非常多setXXX方法。但是你必须知道:赋值胜于method(即【obj.name=xx】>【obj.setName(xx)】)、约定胜于配置:)。

    如果你不是很适应react激进虚拟dom和jsx,如果你反感react放弃了HTML+CSS大量优秀特性功能,如果以后dom性能好了,全世界都i78核+ssd了,那么HTML+CSS才是王道啊。

    observejs也许是你的另一选择,欢迎尝试,感谢对observejs提出那么多宝贵建议和意见的童鞋。

    observejs:https://github.com/kmdjs/observejs
    本文演示:http://kmdjs.github.io/observejs/list/
    本文代码:https://github.com/kmdjs/observejs/tree/master/example/list



沪ICP备19023445号-2号
友情链接