摘要:每個框架類庫被大量用戶大規模使用都說明其戳中了開發者的剛需。但是未執行完的情況下發生人機交互雖然不會報腳本錯誤,但是嚴重影響用戶體驗開發者們被各種爽到之后,這個問題已經被拋到了九霄云外。
寫在前面
因為zepto、jQuery2.x.x和Nuclear都是為現代瀏覽器而出現,不兼容IE8,適合現代瀏覽器的web開發或者移動web/hybrid開發。每個框架類庫被大量用戶大規模使用都說明其戳中了開發者的剛需。本文將對比zepto/jQuery到Nuclear的設計和演化的過程。
無框架時代互聯網的春風剛刮來的時候,人們當時利用三劍客制作網頁。
這里會發現showMsg必須是全局的,onclick觸發才能訪問,這樣就會導致每綁一個事件就要污染一個全局變量。這點問題難不倒前端工程師,加個超級namespace,所有的事件掛在它下面:
但是也有問題,比如這樣的場景:
var SuperNamespce = {}; setTimeout(function () { SuperNamespce.showMsg1 = function () { } SuperNamespce.showMsg2 = function () { } }, 4000)
或者更真實一點:
var SuperNamespce = {}; ajax({ url: "xxx", success: function () { SuperNamespce.showMsg1 = function () { } SuperNamespce.showMsg2 = function () { } } })
在定時器沒執行完成或者AJAX沒有success之前,用戶的所有交互都會報:
Uncaught TypeError: SuperNamespce.showMsg1 is not a function Uncaught TypeError: SuperNamespce.showMsg2 is not a function
然后,善于記錄分析總結思考提煉的工程師們拿出本子記錄下最佳實踐:
不建議在dom元素上直接聲明事件綁定調用
聲明式事件綁定所調用的方法必定要污染全局某個變量
聲明式事件綁定的相關js未執行完的情況下發生人機交互會報腳本錯誤,且嚴重影響用戶體驗
建議在js中先查找dom、再給dom綁定事件
想象一下:一個按鈕5秒后才綁的事件,用戶前4秒內一直點都沒反應,然后5秒到了,但是用戶已經放棄該網頁了。
util庫時代開發者們按照上面總結的最佳實踐,重構了上面的代碼:
這給開發者們帶來了另外一個麻煩的問題,以前聲明式直接在div上綁定事件不需要查找dom,所以不需要標記id,現在每個需要綁定事件的dom都需要標記id用于js查找。而且,這種寫法依舊沒有改變聲明式事件綁定的一個問題:
js未執行完的情況下發生人機交互【雖然不會報腳本錯誤】,但是嚴重影響用戶體驗
比如你div是個按鈕形態,看上去用戶就想點,一直點一直點。但是js還沒執行完,事件還沒綁定上去。用戶將收不到任何反饋。
但是開發者并不關系這‘毫秒’、甚至‘秒’級別的用戶體驗,也有的開發者利用UI邏輯去規避,比如先來個loading?比如綁定完事件再顯示該dom。
就這樣,這個問題就這么不了了之~~~~。隨之而來的是:
查找dom好累,封個類庫:
function query(selector){ //此處省略一萬行代碼 }
綁定事件好累,封個類庫(edwards的events.js):
function addEvent(element, type, handler) { // assign each event handler a unique ID if (!handler.$$guid) handler.$$guid = addEvent.guid++; // create a hash table of event types for the element if (!element.events) element.events = {}; // create a hash table of event handlers for each element/event pair var handlers = element.events[type]; if (!handlers) { handlers = element.events[type] = {}; // store the existing event handler (if there is one) if (element["on" + type]) { handlers[0] = element["on" + type]; } } // store the event handler in the hash table handlers[handler.$$guid] = handler; // assign a global event handler to do all the work element["on" + type] = handleEvent; }; // a counter used to create unique IDs addEvent.guid = 1; function removeEvent(element, type, handler) { // delete the event handler from the hash table if (element.events && element.events[type]) { delete element.events[type][handler.$$guid]; } }; function handleEvent(event) { // grab the event object (IE uses a global event object) event = event || window.event; // get a reference to the hash table of event handlers var handlers = this.events[event.type]; // execute each event handler for (var i in handlers) { this.$$handleEvent = handlers[i]; this.$$handleEvent(event); } };
再然后,開發者們覺得引用這么多工具庫好累...
zepto/jQuery時代開發者們覺得引用這么多工具庫,而且他們其實都隸屬于同一類東西(查找dom、dom綁定事件都是操作dom)可以糅合一起。就有了后來風靡全球的jQuery和zepto在web里實現人機交互:
$("#myID").click(function(){ alert("恭喜你使用三行代碼實現了人機交互程序"); })
開發者的剛需就是:找到dom、綁定事件、寫邏輯。而且,上面的程序還不會丟失語義,一看就知道想干什么。但是:
js未執行完的情況下發生人機交互【雖然不會報腳本錯誤】,但是嚴重影響用戶體驗
開發者們被各種爽到之后,這個問題已經被拋到了九霄云外。那我們就繼續往下看,看到哪個階段把上面這個問題解決了?!
AngularJSAngularJS
因為AngularJS通過ng-click綁定事件,所以沒有解決。
Reactvar Photo = React.createClass({ toggleLiked: function() { this.setState({ liked: !this.state.liked }); }, getInitialState: function() { return { liked: false } }, render: function() { var buttonClass = this.state.liked ? "active" : ""; return () } });
因為React的布局和邏輯放在一起,解決了跨越了十多年之久的前端問題:
js未執行完的情況下發生人機交互【雖然不會報腳本錯誤】,但是嚴重影響用戶體驗
通過把相關的布局和邏輯放在同一個組件中,整個系統變得整潔清晰了。 我們為這個重要的洞見向 React 致敬。(引用于riot)
React的核心根本不是什么UI=fn(state);不用React也可以UI=fn(state)。
Nuclear理念:some HTML + scoped CSS + JS === Reusable Component
Nuclear的網站在這里: http://alloyteam.github.io/Nuclear/ 里面有大量的介紹。
通過下面的使用方式:
var TodoApp = Nuclear.create({ add: function (evt) { evt.preventDefault(); this.option.items.push(this.textBox.value); }, render: function () { return ""; } }); new TodoApp({ items: [] }, "#todoListContainer");TODO
{{#items}}
- {{.}}
{{/items}}
會在html里生成如下的結構:
TODO
更為具體的對應可以看這張圖片:
組件化編程
組件html結構、css和js必須在一起,要么都加載,要么都不加載。
只加載其中一部分都是浪費如css加載了,組件沒用到js加載了,浪費帶寬
帶來不好的體驗,如組件js加載完了,css卻沒加載完成,導致用戶看到錯亂的頁面
腳本錯誤和糟糕體驗,如組件HTML和css加載完了,js卻沒加載完成,導致用戶交互無響應
Nuclear編程
組件化編程
超小的體積,5k
支持任意模板引擎
雙向綁定改善編程體驗
面向對象編程
支持局部CSS
回到最初的問題:
不建議在dom元素上直接聲明事件綁定調用(Nuclear建議事件直接綁在dom上)
聲明式事件綁定所調用的方法必定要污染全局某個變量(只污染了Nuclear)
聲明式事件綁定的相關js未執行完的情況下發生人機交互會報腳本錯誤,且嚴重影響用戶體驗(組件化編程,組件的html、css和js是一個整體)
建議在js中先查找dom、再給dom綁定事件(Nuclear建議事件直接綁在dom上,查找dom的需要可以標記nc-id或者nc-class)
總之:使用Nuclear組件化編程,使組件的HTML、CSS和JS同時一起生效可以規避許多問題。
Github: https://github.com/AlloyTeam/Nuclear
感謝閱讀~~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79312.html
摘要:一般來說,聲明式編程關注于發生了啥,而命令式則同時關注與咋發生的。聲明式編程可以較好地解決這個問題,剛才提到的比較麻煩的元素選擇這個動作可以交托給框架或者庫區處理,這樣就能讓開發者專注于發生了啥,這里推薦一波與。 本文翻譯自FreeCodeCamp的from-zero-to-front-end-hero-part。 繼續譯者的廢話,這篇文章是前端攻略-從路人甲到英雄無敵的下半部分,在...
摘要:目前來看,團隊內部前端項目已全面實施組件化開發。層疊樣式保佑不要污染別的在前端,一般一個組件必須要有骨架和裝飾的以及邏輯。事件綁定條件判斷秒后改變,會自動變更。循環姓名年齡增加修改移除的變更也能監聽到,能夠自動觸發的變更。 目前來看,團隊內部前端項目已全面實施組件化開發。組件化的好處太多,如:按需加載、可復用、易維護、可擴展、少挖坑、不改組件代碼直接切成服務器端渲染(如Nuclear組...
摘要:直搗黃龍黃龍即黃龍府,轄地在今吉林一帶,應該是指長春市農安縣,為金人腹地。一直打到黃龍府。指搗毀敵人的巢穴。有人會說組合優于繼承的。的變更會自動更新依賴的組件??梢圆僮鲗ο髮嵗?,的變更會自動更新組件,屬性設置方法調用。 刀耕火種 刀耕火種是新石器時代殘留的農業經營方式。又稱遷移農業,為原始生荒耕作制。 var TodoApp = Nuclear.create({ add: f...
閱讀 3192·2023-04-26 01:39
閱讀 3345·2023-04-25 18:09
閱讀 1612·2021-10-08 10:05
閱讀 3228·2021-09-22 15:45
閱讀 2758·2019-08-30 15:55
閱讀 2393·2019-08-30 15:54
閱讀 3167·2019-08-30 15:53
閱讀 1324·2019-08-29 12:32