转载

observejs改善组件开发体验

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 =   '<div class="list-group" style="  text-align: center;width:<%=typeof width === "number"?width+"px":width%>;" >'   + '   <% for ( var i = 0, len = data.length; i < len; i++) { %>'   + '<%  var item = data[i]; %>'   + '<a class="list-group-item <%=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);   var nodes = this.parent.querySelectorAll(".list-group"), index = nodes.length - 1;   this.node = nodes[index];  },  clear:function(){   this.data.size(0);  },  remove:function(index){   this.data.splice(index,1);  },  add:function(item){   list.data.push(item);  },  edit:function(index,item){   list.data[index]=item;  },  disable:function(index){   list.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);   };  }, } 

组件使用

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); 

组件分析

其中仅需要一行

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。

如果你不是很适应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

正文到此结束
Loading...