• 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只是一个简单的例子,旨在抛砖引玉,但核心思想就是这样的。具体的代码实现还是需要大家不断的完善,扩展,知识在于分享以及博众取长。

    追求卓越,成功就会跟着你走!
  • 相关阅读:
    高并发、高性能、高可用
    性能优化 = 改改代码?
    高级开发必须理解的Java中SPI机制
    java性能优化的50个细节(珍藏版)
    Java API 设计清单
    QString与QByteArray互相转换的方法
    QT 托盘 hover事件捕捉
    qt捕获全局windows消息
    前端开发树形插件带来的烦恼(一)
    靠谱的div引入任何外链内容
  • 原文地址:https://www.cnblogs.com/wlf0502/p/5076790.html
Copyright © 2020-2023  润新知