首先这些年关于前端技术层出不穷,从最先的只用js作简单验证,到如今发现好像大前端已经无所不能了的感受。特别是为了下降前端开发复杂度,涌现了一大批 的MVC/MVVM模式的前端框架,不停了刷新咱们的代码组织结构及开发模式,好比:BackboneJS、EmberJS、KnockoutJS、 AvalonJS(国产)、AngularJS、ReactJS等等。 css
咱们的开发模式第一次革命应该算是从google提出ajax一直到nodejs变化是很是的大,咱们也在尝试着找到更合理更简单更适合的开发模式。我自 己也经历过从原生js的开发到使用jquery操做dom,再到应用knockoutjs、avalonjs、angularjs及reactjs到咱们 的项目中(backbonejs、emberjs、polymer我没实际使用过),发现咱们的程序越写越简单,并且愈来愈有意思。但每一个框架专一点是不 同样的,并且也有一些缺点:
一、angularjs,体积庞大过于复杂不适合轻量级应用,并且我对1.3放弃IE8及2.0的跳跃式发展耿耿于怀,最终开始把目光投向reactjs。
二、reactjs,研究了一段时间发现还真不错,首先是比较轻量极,性能也是很赞,最主要是它提出的Virtual DOM的概念,我以为也算是一个革新了,可是它其实算不上是一个框架,它的专一点在于生成UI,就跟ng中的directive一个等级的,因此不少东西 还要本身实现,它只能算咱们的一个利器要架构一个复杂的应用还须要不少的工做。还有一点就是我比较不喜欢它的jsx这个玩意,虽然它能够在服务端处理。应 该算是个人我的偏见吧。
三、polymer理念很超前,基于web component实现,我我的也以为这是将来的趋势。
可是目前来讲对于Shadow DOM的浏览器的兼容性:http://caniuse.mojijs.com/Home/Html/item/key/shadowdom/index.html,我估计除了研究没人会想用它了,并且它还利用了html5的imports:http://www.html5rocks.com/en/tutorials/webcomponents/imports/,它这种模式产生的问题很是明显,就是须要import太多的html,并且还有嵌套的概念,可想而知。html
这些框架都很强悍,可是我以为实际开发,一个适合好用的框架应该是要把已有的类库、插件等等的这些完美的结合起,而且提供简单易用的接口及合理的代码组织 结构,现有的jquery插件很是的多(其实jquery比这些东西流行的多的多),现有的开源不少的类库咱们均可以使用。个人思路是现有的这些资源应该 要充分利用起来。因此我想本身整一个框架出来。我构想设计了下:前端
一、web component思路,结合Shadow DOM 及 Virtual DOM,若是支持Shadom DOM就使用Shadom DOM不然使用Virtual DOM实现。
二、控件定义尽可能简单易懂,可快速包装现有的插件,控件存在继承的概念,控件存在少许修改时能够考虑继承覆写的方式实现。
三、实现MVVM的双向绑定,实际是三向(实际dom,控件实例(不管是shadow仍是virtual都对应到一个virtual dom)、数据)html5
我暂时把这个项目叫作 Chitu.js 即赤兔.js,接下来会放到github上。 java
一、标签订义
好比咱们须要一个hello的控件 node
<hello id="id1" binding="hello1"></hello>
二、控件定义
咱们定义hello的控件 react
chitu.component('hello', function (self) { //属性定义 self.name = { get: function () { return self.root.getAttribute("name"); }, set: function (value) { self.root.setAttribute("name", value); } }; self.value = { get: function () { return self.root.innerText; }, set: function (value) { self.root.innerText = value; } }; //... //事件定义 self.onclick = function(){ }; //... //方法定义 self.setColor = function(color){ self.root.style.color = color; }; //... //控件生成 self.render = function () { //... var text = document.createTextNode(self.value); return text; }; //控件消亡 self.dispose = function(){ }; });
这里就是整个hello的控件的定义,就是把hello控件实例看做一个virtual节点,这是reactjs的思路,可是实现上面若是是支持shadow dom可使用把render中返回的节点放到shadow dom中。jquery
这里的控件属性与实际dom的双向连动是经过引入get set方法来实现的,实际上这个代码还须要通过一次complie处理,把get set方法经过ES5的Object.defineProperty方法转换成属性(先不考虑兼容性)。git
这里若是要集成jquery控件就很是容易了,好比combobox控件:angularjs
chitu.component('combobox', function(self){ self.value = { get:function(){return $(root).combobox('getValue');}, set:function(value){$(root).combobox('setValue',value);} }; self.render = function(){ $(root).combobox(options); return root; }; self.dispose = function(){ $(root).combobox('dispose'); }; });
若是控件须要继承能够这样,定义一个mygridEx继承mygrid控件
chitu.component('mygridEx', function(self){ //覆写属性 self.attr1 = { get:function(){}, set:function(){} }; //覆写方法 self.getRowCount = function(){ } },'mygrid');
三、控制器
chitu.controller('ctrl1',function(scope){ scope.data ={ tenant_id:'001', tenant_name:'tenantname', height:100 }; scope.hello={ name:'helloname', value:'world' } scope.grid1 ={ width:500, height:'{data.height}', rowClick:function(row){ scope.vdom.id1.value = row.name; } }; scope.search1={ text:'{data.teannt_name}', searchClick:function(){ } }; });
这里须要解释下<hello id="id1" binding="hello1"></hello>
这里的binding实际上对应的是controller当中的属性,这个属性其实就是控件的选项参数,咱们之前调用jquery控件时
$('#id').jqgrid({
//一堆参数 });
这样的话,这一堆参数就能够经过一个binding跟页面联系起来,方便控件的使用,固然还能够在控件定义时就定义好不少默认的参数,只须要传入须要改变的参数。
固然咱们的参数也不必定都要写在binding当中,也能够单独绑定控件属性
<hello id="id1" [value]="world" ></hello> <hello id="id1" [value]="{data.tenant_name}" ></hello> <hello id="id1" binding="hello1" [value]="world" [onclick]="search1.searchClick"></hello>
第一行:没有对应的binding属性,只有一个value属性,value的值为world
第二行:value的值双向绑定到controller中的data.tenant_name数据上
第三行:先从bindig的hello1中取值,若是有[value]则覆盖原值
这里为何给属性加上[中括号],是由于属性叫什么名字均可能,尽可能避免和原dom属性冲突。
控件器中还有一点设计值得说的是,咱们能够把数据集中在scope.data中
一、其它地方绑定只须要{data.row1.field1}这样指定绑定就好
二、咱们能够不须要先data中的结构是怎么样子,根据绑定关系生成data的结构
三、大多数状况下咱们取回来的数据就是一个返回result,咱们直接赋值给scope.data便可,不须要hello1.value = result.name , grid1.data = result.list;这样的处理。
四、咱们须要提交数据时,也只须要从data中取便可,很是方便
固然对于普通的标签,咱们也是能够绑定的
<div [title]="{data.title}" [text]="{data.text}" [onclick]="search1.searchClick" ></div>
这样一来,咱们的代码可能就会集中在controller的一些方法当前中了,咱们在controller中能够直接获取到每一个控件实例,能够直接访问控件的各个属性便可实现交互。
固然若是有绑定到data数据中,直接操做数据也能够实现ui交互了。
上面我给你们描述了个人思路及想法,咱们再分析可能面对的问题。
一、兼容性
目前只是在尝试阶段,不少问题还没碰到,个人目标是尽可能作到IE8+
二、性能
关于性能的消耗,可能主要是在于节点扫描、控件render、属性绑定及属性频繁的刷新。节点扫描固然会有些消耗,可是它带来的方便性能够忽略它的消耗, 除非你想一个一个控件指定去手动调用,控件render就取决了你写的控件自己了,不算是这个框架的问题,属性绑定在数据量没有大到必定程度是基本是不会 有问题的。
三、开发效率
开发效率主要就取决因而否作到了关注点分离,代码组织是否清晰合理简单易懂,代码只须要写有变化的东西,把重复的细节都封装起来,这个只能是尽可能作到了。
关于个人其它的一些想法
一、需不须要引入相似css的东西用于分离页面与controller之间的绑定,这样还能够去除节点扫描,提升性能,以下
var binding={ '#id':'todo1', '#grid1':'grid', '#hello1':'hello' };
二、关于render处理
a、用代码实现(原生、jquery)
b、模板实现或拼接字符串
c、经过预生成的方式(相似jsx,也可经过nodejs c# java等语言)
三、关于属性刷新
由于控件属性是直接绑定到原生的dom上的,若是出现了大量的属性刷新恐带来性能问题,是否考虑一个参数用来开启关闭(当即刷新、一次性刷新)
四、跟amd cmd结合
这个是没有任何问题的,并且若是控件都是包装第三方控件的话,实现动态加载还能够更加的方便。
五、是否还须要引入其它特性,如ng注入特性、过滤器等
六、哪些环节还能够在服务端预处理
目前只是把个人想法记录起来,有不少问题可能还没具体想清楚,如今本身先实现了一个简易的版本,等我先折腾出一个0.1的版本放到github上,若是有兴趣的朋友,能够加入一块儿设计构思及开发。你们有好的想法,意见建议欢迎给我留言