web前端架構


  每個人都有一部手機,可以將其當做我們的前端模塊,在這個模塊的內部,我可以干各種事,玩游戲,看視頻,聽音樂等等,不會跟你的手機有任何關聯,也就是解耦了。那么問題來了,是模塊總是要通信的呀,該怎么通信呢?上圖:

 

  A手機想要和其他手機通信,是必須經過運營商的,所以我們的前端模塊之間需要進行通信,也需要一個類似於運營商的東西,而該東西就是整個架構的核心,那就是事件管理者(EventManager)。通過事件管理者,當A模塊需要調用B模塊里面的render方法時,A模塊將會通過事件管理者通知B模塊執行它的render方法。反之,當B模塊需要調用A模塊的get方法時,也通過事件管理者,通知A模塊執行它的get方法。這樣A模塊中不會存在B模塊的字樣,B模塊中也不存在A模塊的字樣,它們中只會存在EventManager,一個為二者建立通信的通道。

      這其實就是設計模式中的觀察者模式,也稱之為發布訂閱模式。上面提到的事件已經不單是瀏覽器自帶的那些事件(click,move等),它是有一定含義的自定義事件,可以起任何名稱,比如:'dataChange'(數據改變事件),'render'(數據渲染事件),'clear'(頁面清空事件)。模塊內部,我們分層進行開發,采用mvc或者mvvm的開發方式。mvc只是一種設計思想,可以將model,view,controller分三個js文件開發,也可以在一個js文件中實現3種層次,另外controller過於臃腫的情況下,我們對其可以進行二次乃至三次分層,例如可以分成業務層,服務層等。我想說的是,mvc只是一種思想,它沒有規定你必須幾個文件,怎么書寫,怎么具體分層,我們完全可以在符合思想的情況下為所欲為。結構如圖:

  

      

上例子:

1、模塊A:

 1 T.ModuleA = {
 2     init:function(){
 3 
 4         // 事件監聽,監聽清空事件
 5         T.EventManager.addEvent('clear', this.clear, this);
 6     },
 7 
 8     clear:function(id){
 9         document.getElementById(id).innerHTML = '';
10     }
11 }

2、模塊B:

 1 T.ModuleB = {
 2     init:function(){
 3 
 4         // 事件監聽,監聽清空事件
 5         T.EventManager.addEvent('clear', this.clear, this);
 6     },
 7 
 8     clear:function(id){
 9         document.getElementById(id).innerHTML = '';
10     }
11 }

3、事件管理類:

 1 T.EventManager = {
 2 
 3     // 事件容器
 4     eventContianer:{},
 5 
 6     /**
 7      * 事件監聽函數
 8      * @param {string}   evtName    事件名稱
 9      * @param {function} fn         函數引用
10      * @param {obj}      ctx        上下文環境
11      */
12     addEvent:function(evtName, fn, ctx){
13 
14         var obj = {'fn':fn, 'ctx':ctx};
15 
16         if(!this.eventContianer[evtName]){
17             this.eventContianer[evtName] = [];
18         }
19 
20         this.eventContianer[evtName].push(obj);
21     },
22 
23     /**
24      * 派發事件
25      * @param  {string} evtName 需要觸發的事件名稱
26      * @param  {array}  args    需要傳遞給事件回調函數的參數
27      */
28     dispatchEvent:function(evtName, args){
29         var item, evts = this.eventContianer[evtName];
30 
31         // 事件沒有注冊,不派發
32         if(!evts){
33             return;
34         }
35 
36         for (var i = 0; i < evts.length; i++) {
37             var obj = evts[i];
38 
39             if (Array.isArray(args)) {
40                 if(args[i]){
41                     item = args[i];
42                 } else {
43                     item = null;
44                 }
45             } else {
46                 item = args;
47             }
48 
49             obj.fn.call(obj.ctx, item);
50         }
51     }
52 }

4、頁面展示

 1 <!DOCTYPE html> 
 2 <html> 
 3 <head> 
 4 <meta http-equiv="content-type" content="text/html; charset=utf-8"/> 
 5 <script type="text/javascript">
 6     window.T = window.T || {};
 7 </script>
 8 <script type="text/javascript" src="EventManager.js"></script>
 9 <script type="text/javascript" src="ModuleA.js"></script>
10 <script type="text/javascript" src="ModuleB.js"></script>
11 <style type="text/css">
12     div{
13         border: 1px solid black;
14     }
15 
16     #moduleA{
17         background-color: yellow;
18     }
19 
20     #moduleB{
21         background-color: green;
22     }
23 </style>
24 </head> 
25 <body>
26     <div id="moduleA">我是模塊A</div>
27     <div id="moduleB">我是模塊B</div>
28     <input id="clear" type="button" value="清空"/>
29     <script type="text/javascript">
30         T.ModuleA.init();
31         T.ModuleB.init();
32         document.getElementById('clear').onclick=function(){
33             T.EventManager.dispatchEvent('clear', ['moduleA','moduleB']);
34         }
35     </script>
36 </body> 
37 </html>

上面的例子,展示了事件廣播的特性,模塊A監聽clear事件,模塊B監聽clear事件,事件管理器,觸發clear事件,同時清空模塊A的內容和模塊B的內容。有點類似於運營商向每台手機發送消息。

這個demo只是一個簡單的例子,旨在拋磚引玉,但核心思想就是這樣的。具體的代碼實現還是需要大家不斷的完善,擴展,知識在於分享以及博眾取長。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM