<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

     


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


    網站導航:
     
    主站蜘蛛池模板: 精品视频一区二区三区免费| GOGOGO高清免费看韩国| 日本h在线精品免费观看| 国产国拍亚洲精品福利 | a级男女仿爱免费视频| 久久精品国产亚洲精品| a一级爱做片免费| 日韩亚洲变态另类中文| 久久久久久噜噜精品免费直播| 亚洲午夜无码AV毛片久久| 国产精品美女免费视频观看| 91麻豆国产自产在线观看亚洲 | 免费人成网站永久| 啊v在线免费观看| 九一在线完整视频免费观看| 国产成人毛片亚洲精品| 精品国产污污免费网站 | 亚洲日韩av无码中文| 又黄又爽一线毛片免费观看 | 国产L精品国产亚洲区久久| 一个人看的免费视频www在线高清动漫 | 无码不卡亚洲成?人片| 暖暖免费中文在线日本| 亚洲日韩精品一区二区三区无码| 精品亚洲永久免费精品| 亚洲日本人成中文字幕| 免费看国产曰批40分钟| 两个人看的www高清免费视频 | 亚洲AV无码成人精品区大在线| 中文字幕在线视频免费观看| 亚洲天堂中文字幕| 一区二区无码免费视频网站| 免费视频成人国产精品网站 | 国产成人啪精品视频免费网| 精品久久久久久国产免费了| 久久精品国产亚洲AV电影| 日韩吃奶摸下AA片免费观看| 一个人晚上在线观看的免费视频| 亚洲精品无码不卡| 日韩在线天堂免费观看| 成人无码WWW免费视频|