Eng 0.9.4 组件循环通信响应 --- (解决watch噩梦 , 群发循环响应难题 )

536 阅读3分钟


           Eng 刚刚迎来了0.9.4的最新版本 , 除了解决所有已知的bug  , 最主要的新特性 就是增加了组件( 循环通信响应 ).

           众所周知组件间互相watch 响应 , 如果没有加入判断条件  , 则会进入死循环状态 ,  而且如果双方都必须对对方的通信做出明确响应的时候 , 双方都不得不要做好对相应数据内容的判断 , 防止僵死.

         两个组件尚且如此复杂 , 如果一个特殊的组件群 ,彼此群发循环响应 , 这个判断你来怎么写 ? 是不是比初涉node 时的 回调噩梦 还要可怕?  这简直就是 watch 噩梦

下面进入正题:

  • PS : Eng 实行组件闭包全局无关的思想 (所有该组件的相关操作都应写在created方法内),  所以Eng 即使在完全闭包的情况下 , 也能与所有已存在和将要添加的组件通信 , 访问操纵其所有的参数方法  , 前提你必须声明这些组件id和谁有关

html

<div id='app1'>
    <p>成员 : {{name}}</p>
    <p>{{msg}}</p>
</div>

<div id='app2'>
     <p>成员 : {{name}}</p>
     <p>{{msg}}</p>
</div>

<div id='app3'>
     <p>成员 : {{name}}</p>
     <p>{{msg}}</p>
</div>

javascript

var app1=new Eng({
         el:document.getElementById('app1'),
         id:'app1',
         relate:['app2','app3'],  //和app1有关的组件id列表
         watcher:{
             msg:function( oldValue ,newValue, items ,cache){ //以下简写

                    var member=items.$_relate; // == [app1,app2] 已关联的组件

                    var l=member.length;

                    if(newValue=='')return;

                    // 这里判断newValue是否为空 , 是因为 Eng 的watch 是立即执行的
                    // $_watcher 才是先注册后触发
                 
                    items.$_caller=true; // 主叫

                    while(l--){

                        var app= items[member[l]];

                            app.$_gData.msg=items.$_id+' : '+newValue;
                   }
          },
          data:{
                name:'app1',
                msg:'',
         },
         created:function(items , cache){

         //items.$_watcher({xxx:fun(){}}) 如果不想立即触发watcher

        }
});


var app2=new Eng({
           el:document.getElementById('app2'),
           id:'app2',
           relate:['app1','app3'],
           watcher:{
                 msg:function( o ,n, i ,c){

                        var m=i.$_relate;

                        var l=m.length;

                            if(n=='')return;

                            i.$_caller=true;

                            while(l--){

                               var a= i[m[l]];

                                   a.$_gData.msg=i.$_id+' : '+n;

                            };
                 }
           },
           data:{
                 name:'app2',
                 msg:''
           }
});	

var app3=new Eng(
            el:document.getElementById('app3'),
            id:'app2',
            relate:['app1','app3'],
            watcher:{                 
                    msg:function( o ,n, i ,c){

                        var m=i.$_relate;

                        var l=m.length;

                            if(n=='')return;

                            i.$_caller=true;

                            while(l--){

                              var a= i[m[l]];

                                  a.$_gData.msg=i.$_id+' : '+n;

                           };
                  }
           },
           data:{
                 name:'app2',
                 msg:''
           }
});

      从上面代码中 relate 参数告知了组件我和哪些 id 的组件有关 , 即使是后添加的组件 , 也能顺利关联 ,事实上只要其中一方关联 , 对方 的items参数中就会包含对方 , items.$id_+ idname

      而且通过watcher关系 我们可以看到这三个组件都是有彼此群发响应通信关系的 , 都 监控 msg 的值变化  , 也都没有互相判断 响应 成立条件 .            

     因为 items.$_caller = true;  主叫机制 , 从底层断开了watch 的死循环的可能 . 可以理解为:现在我是主叫 , 你们都老老实实听我说话  , 不得插嘴..

    到此, 完美诠释了Eng 循环群发通信相应机制的应用实现 .  可能有些同学对此嗤之以鼻  , 但是你不妨通过 不使用Eng 的主叫机制  ,  或者用其它 同类js 工具的watch 实现 群发循环通信响应试试  , 我想绝非易事.....


下面进入命令截图阶段:

原始画面:


app1.msg=' 好久不见! 十分想念! 互相问个好呗 ?'


app2.msg=' 是啊 好久不见 , 你们好';

app3.msg=' 哎! app1和app2 上次一别 , 久矣!'

感兴趣的同学 , 可以尝试 编写自己的场景多员群发通信小游戏


总结 : 加入 items.$_caller=true 的主叫声明机制  ,  将事件群发的主控判断权牢牢掌握在主叫手中  , 仅需"主叫"调度控制  ,  无需 "被叫" 端做任何数据判断 ,  做到只管发不管收  ,  成功的避免了在混乱的组件群发通信响应时大量的逻辑判断  .  尤其在循环响应时  , 更免除了逻辑渗漏会陷入 watch噩梦 的隐患.