<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    TWaver - 專注UI技術

    http://twaver.servasoft.com/
    posts - 171, comments - 191, trackbacks - 0, articles - 2
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    接上一回TWaver HTML5 + Node.js + express + socket.io + redis(四), 這一篇您將了解到

    1. 如何保存更改后的拓撲數據 (包括新增的, 修改的, 刪除的)
    2. 如何廣播更改后的拓撲數據 (僅僅廣播更改的數據)

    下面是mac和iphone上的效果圖, mac或iphone上的修改都將及時互相同步:



    一. 先來看后臺如何實現
    后臺需要做兩件事情: 保存修改以及廣播修改; 其中修改又分為是新增, 修改, 還是刪除. 保存修改很容易, 無非就是對數據庫的增刪改, 廣播數據也很容易, 調用Socket.emit之前, 先設置廣播標記就ok了: Socket.broadcast.emit. 而且這個廣播只會通知其他客戶端, 發送這個廣播的客戶端不會收到廣播, 這正好是我們需要的, 所以后臺代碼就好寫了:
    添加保存數據的socket.io監聽, 里面保存數據后, 廣播之:
     1     //保存數據
     2     client.on('saveData', function (datas) {
     3         if (!datas) {
     4             return;
     5         }
     6         //保存新增網元
     7         save(datas.add);
     8         //保存修改網元
     9         save(datas.change);
    10         //刪除網元
    11         remove(datas.remove);
    12         //廣播更新
    13         client.broadcast.emit('broadcast', datas);
    14     });
    保存數據的函數如下:
     1 //保存網元
     2 function save (datas) {
     3     if(!datas){
     4         return;
     5     }
     6     var elements = {};
     7     for (var i=0,n=datas.length,data; i<n; i++) {
     8         data = datas[i];
     9         elements[data.id] = JSON.stringify(data);
    10     }
    11     redis.hmset('datas', elements);
    12 };
    13 
    14 //刪除網元
    15 function remove (datas) {
    16     if(!datas){
    17         return;
    18     }
    19     var ids = [];
    20     for (var i=0,n=datas.length; i<n; i++) {
    21         ids.push(datas[i].id);
    22     }
    23     redis.hdel('datas', ids);
    24 };

    二. 前臺實現
    分兩步: 監聽數據的增刪改并自動保存, 響應廣播更新
    1. 監聽數據的增刪改并自動保存
    TWaver HTML5的數據模型提供了各種監聽器, 以便在數據更改后做響應處理. 其中:
    DataBox.addDataPropertyChangeListener用于監聽數據容器里數據的屬性變化, 也即對數據的修改, 其回調函數的參數包含屬性: property(發生變化的屬性), oldValue(舊值), newValue(新值), source(發生變化的數據)
    DataBox.addDataBoxChangeListener用于監聽數據容器的變化, 也即數據的添加, 刪除以及清空, 其回調函數的參數包含屬性: kind(容器變化類型, 可選值為add(新增), remove(刪除), clear(清空)), data(新增或刪除的數據), datas(清空的數據集合)
    這里實現保存數據的思路是:
    i> 如果有網元被修改, 則將被修改的網元加上change標記, 其中判斷isChanging標志很重要, 因為需要用此標志區分是用戶更改還是響應廣播更新(也即程序更新)
     1     //添加網元屬性更改監聽器
     2     box.addDataPropertyChangeListener(function (e) {
     3         //如果正在響應廣播更新,則返回
     4         if (isChanging) {
     5             return;
     6         }
     7         //如果屬性為add, change 則返回
     8         if (e.property === 'C:add' || e.property === 'C:change') {
     9             return;
    10         }
    11         //設置保存數據標記
    12         needSave = true;
    13         //將有屬性更改的節點置上change標記
    14         e.source.setClient('change', true);
    15     });
    ii> 如果有新增網元, 則將新增網元加上add標記, 如果有網元被刪除, 則存入map中
     1     //添加數據容器更改監聽器
     2     box.addDataBoxChangeListener( function (e) {
     3         //如果正在響應廣播更新,則返回
     4         if (isChanging) {
     5             return;
     6         }
     7         //設置保存數據標記
     8         needSave = true;
     9         if (e.kind === 'add') {
    10             //將新增的節點置上add標記
    11             e.data.setClient('add', true);
    12         } else if (e.kind === 'remove') {
    13             //如果網元沒有新增標記, 則存儲到被刪除網元列表中
    14             if (!e.data.getClient('add')) {
    15                 //存儲被刪除網元
    16                 removedElements[e.data.getId()] = e.data;
    17             }
    18         }
    19     });

    iii> 啟動定時器, 保存更改
    定時器代碼如下:
     1 //自動保存
     2 function setAutoSave (value) {
     3     if(value){
     4         //定時器,每隔1秒鐘保存修改
     5         timer = setInterval(function(){
     6             save();
     7         }, 1000);
     8     }else{
     9         window.clearTimeout(timer);
    10     }
    11 }
    保存數據代碼如下, 需要注意的是, 得到要添加和被修改的網元后, 需要將其add和change標記置為false, 以避免重復保存:
     1 //保存數據
     2 function save () {
     3     //如果無數據添加、修改、刪除,則直接返回
     4     if(!needSave){
     5         return;
     6     }
     7     
     8     var add = [];
     9     var change = [];
    10     var remove = [];
    11     isChanging = true;
    12     box.forEach(function(data){
    13         //新增的網元
    14         if(data.getClient('add')){
    15             add.push(toData(data));
    16         }
    17         //修改的網元
    18         else if(data.getClient('change')){
    19             change.push(toData(data));
    20         }
    21         //清除網元新增和修改標記
    22         data.setClient('add', false);
    23         data.setClient('change', false);
    24     });
    25     isChanging = false;
    26     //刪除的網元
    27     for(var id in removedElements){
    28         remove.push(toData(removedElements[id]));
    29     }
    30     
    31     if(add.length == 0 && change.length == 0 && remove.length == 0){
    32         return;
    33     }
    34     
    35     //初始化待刪除數據
    36     removedElements = {};
    37     //還原保存數據標記
    38     needSave = false;
    39     //構造更新數據
    40     var datas = {};
    41     if(add.length != 0){
    42         datas.add = add;
    43     }
    44     if(remove.length != 0){
    45         datas.remove = remove;
    46     }
    47     if(change.length != 0){
    48         datas.change = change;
    49     }
    50     socket.emit('saveData', datas);
    51 }
    從網元獲取要持久化的數據代碼如下:
     1 //從網元獲取持久化數據
     2 function toData (element) {
     3     if(element instanceof twaver.Node) {
     4         return {
     5             id: element.getId(),
     6             name: element.getName(),
     7             location: element.getLocation()
     8         };
     9     } else {
    10         return {
    11             id: element.getId(),
    12             name: element.getName(),
    13             from: element.getFromNode() ? element.getFromNode().getId() : null,
    14             to: element.getToNode() ? element.getToNode().getId() : null
    15         };
    16     }
    17 }

    2. 響應廣播更新
    分為新增, 刪除以及修改三種情況, 其中很重要的是在做這些事情之前先設置isChanging為true, 以防止重復廣播更新
     1 //響應廣播更新
     2 function onBroadcast (data) {
     3     if (!data) {
     4         return;
     5     }
     6     //設置響應廣播更新標記,防止重復更新
     7     isChanging = true;
     8     var i, c, add=data.add, change=data.change, remove=data.remove;
     9     //添加節點
    10     if (add) {
    11         for (i=0,c=add.length; i<c; i++) {
    12             if (add[i].from) {
    13                 addLink(add[i]);
    14             } else {
    15                 addNode(add[i]);
    16             }
    17         }
    18     }
    19     //修改節點
    20     if (change) {
    21         for (i=0,c=change.length; i<c; i++) {
    22             changeData(change[i]);
    23         }
    24     }
    25     //刪除節點
    26     if (remove) {
    27         for (i=0,c=remove.length; i<c; i++) {
    28             removeData(remove[i]);
    29         }
    30     }
    31     //還原更新廣播數據
    32     isChanging = false;
    33 }
    增刪改網元代碼如下:
     1 //添加節點
     2 function addNode (data) {
     3     //構造節點
     4     var node = new twaver.Node(data);
     5     //添加節點
     6     box.add(node);
     7 }
     8 
     9 //添加節點
    10 function addLink (data) {
    11     //查找from節點
    12     var from = box.getDataById(data.from);
    13     //查找to節點
    14     var to = box.getDataById(data.to);
    15     //構造連線
    16     var link = new twaver.Link({id: data.id, name: data.name}, from, to);
    17     //添加連線
    18     box.add(link);
    19 }
    20 
    21 //修改網元
    22 function changeData (data) {
    23     var element = box.getDataById(data.id);
    24     //修改節點
    25     if (element instanceof twaver.Node) {
    26         element.setLocation(data.location.x, data.location.y);
    27         element.setName(data.name);
    28     }
    29     //修改連線
    30     else if (element instanceof twaver.Link) {
    31         element.setName(data.name);
    32         element.setFromNode(box.getDataById(data.from));
    33         element.setToNode(box.getDataById(data.to));
    34     }
    35     //網元被刪除
    36     else {
    37         //網元被刪除, 無需修改
    38     }
    39 }
    40 
    41 //刪除網元
    42 function removeData (data) {
    43     box.removeById(data.id);
    44 }

    最后, 附上本文的完整demo:TWaverHTML5Demo

     


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 在线综合亚洲中文精品| 成人免费夜片在线观看| 精品久久免费视频| 亚洲一区二区三区免费| 亚洲国产精品VA在线看黑人| 日韩版码免费福利视频| 二级毛片免费观看全程| 亚洲毛片无码专区亚洲乱| 国产午夜免费秋霞影院| 日韩免费观看一区| 亚洲av永久无码天堂网| 国产亚洲成AV人片在线观黄桃| 亚洲免费综合色在线视频| 国产精品hd免费观看| 亚洲avav天堂av在线网爱情| 亚洲性日韩精品国产一区二区| 亚洲一区二区免费视频| 永久免费无码网站在线观看个| 亚洲精品mv在线观看| 亚洲精品麻豆av| 国产成人免费高清激情视频| 成在线人视频免费视频| 亚洲日韩av无码中文| 久久久久亚洲AV成人无码| 国产一级理论免费版| 99久久久精品免费观看国产| 久久久免费观成人影院| 亚洲av中文无码乱人伦在线观看| 亚洲国产综合专区在线电影 | 无码精品A∨在线观看免费| 思思久久99热免费精品6| 中文字幕无码精品亚洲资源网久久| 亚洲精品无码久久久久| 成人亚洲综合天堂| 九九精品免费视频| 久久国产精品免费网站| 免费一区二区三区在线视频| 亚洲人成网站在线在线观看| 亚洲欧洲精品久久| 亚洲爆乳无码专区| 亚洲一区爱区精品无码|