首先這些年關於前端技術層出不窮,從最先的只用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上,若是有興趣的朋友,能夠加入一塊兒設計構思及開發。你們有好的想法,意見建議歡迎給我留言