2016-04-04 10 views
8

Aurelia、RethinkDB & Socket.IOのシンプルなTODOアプリから始めます。私はSocket.IOで変更されたオブジェクトの再レンダリングや再評価に問題があるようです。基本的に、最初のブラウザではすべてがうまくいきますが、2番目のブラウザでは再レンダリングされませんが、コンソールにオブジェクトを表示するとオブジェクトの違いが表示されます。この問題はオブジェクトの更新時のみであり、todoアイテムの配列からオブジェクトを作成/削除する際には完全に機能します。Aureliaでバインディングの再評価または再レンダリングを強制する方法

HTML RethinkDBと

<ul> 
    <li repeat.for="item of items"> 
     <div show.bind="!item.isEditing"> 
     <input type="checkbox" checked.two-way="item.completed" click.delegate="toggleComplete(item)" /> 
     <label class="${item.completed ? 'done': ''} ${item.archived ? 'archived' : ''}" click.delegate="$parent.editBegin(item)"> 
      ${item.title} 
     </label> 
     <a href="#" click.delegate="$parent.deleteItem(item, $event)"><i class="glyphicon glyphicon-trash"></i></a> 
     </div> 
     <div show.bind="item.isEditing"> 
     <form submit.delegate="$parent.editEnd(item)"> 
      <input type="text" value.bind="item.title" blur.delegate="$parent.editEnd(item)" /> 
     </form> 
     </div> 
    </li> 
    </ul> 

NodeJSはSocket.on

// update item 
socket.on("todo_update", data => { 
    let pos = arrayFindObjectIndex(this.items, 'id', data.id); 
    if(pos >= 0) { 
    console.log('before update'); 
    console.log(this.items[pos]); 
    this.items[pos] = data; 
    this.items[pos].title = this.items[pos].title + ' [updated]'; 
    console.log('after update'); 
    console.log(this.items[pos]); 
    } 
}); 

// create item, only add the item if we don't have it already in the items list to avoid dupes 
socket.on("todo_create", data => { 
    if (!_.some(this.items, function (p) { 
    return p.id === data.id; 
    })) { 
    this.items.unshift(data); 
    } 
}); 

// delete item, only delete item if found in items list 
socket.on("todo_delete", data => { 
    let pos = arrayFindObjectIndex(this.items, 'id', data.id); 
    if(pos >= 0) { 
    this.items.splice(pos, 1); 
    } 
}); 

socket.on("todo_update", ...){}は、2番目のブラウザの再レンダリングすることなく、表示されていないを見て

// attach a RethinkDB changefeeds to watch any changes 
r.table(config.table) 
    .changes() 
    .run() 
    .then(function(cursor) { 
     //cursor.each(console.log); 
     cursor.each(function(err, item) { 
     if (!!item && !!item.new_val && item.old_val == null) { 
      io.sockets.emit("todo_create", item.new_val); 
     }else if (!!item && !!item.new_val && !!item.old_val) { 
      io.sockets.emit("todo_update", item.new_val); 
     }else if(!!item && item.new_val == null && !!item.old_val) { 
      io.sockets.emit("todo_delete", item.old_val); 
     } 
     }); 
    }) 
    .error(function(err){ 
     console.log("Changefeeds Failure: ", err); 
    }); 

オーレリアコードをchangefeedsアップデート前/後のコンソールのオブジェクトに違いがあるオブジェクトそのもの。私はtodoのタイトルプロパティを変更しても、それも再レンダリングされません。

新しいオブジェクトのプロパティで2番目のブラウザでAureliaを再レンダリングするにはどうすればよいですか?私はあまりにも難しくありません。私はAurelia/RethinkDB/NodeJS/Socket.IOをいつも学んでいます...

答えて

16

Aureliaは配列のミューテータメソッドをオーバーライドすることによって配列の内容の変更を観察します、ポップ、スプライス、シフトなど)。これは、ほとんどのユースケースでうまく動作し、本当にうまく動作します(ダーティーチェックなし、メモリとCPUの面で非常に軽い)。残念ながら、これは、aureliaが「見る」ことができない配列を突然変異させる1つの方法を残します:インデックスされた割り当て...例えばmyArray[6] = 'foo'。配列メソッドが呼び出されていないので、バインディングシステムは変更された配列を認識しません。私が知りたかったし、変更によってどこか...その文書があるダーティチェックの外にとどまり、まさに

// update item 
socket.on("todo_update", data => { 
    let pos = arrayFindObjectIndex(this.items, 'id', data.id); 
    if(pos >= 0) { 
    console.log('before update'); 
    console.log(this.items[pos]); 

    this.items[pos] = data; // <-- change this to: this.items.splice(pos, 1, data); 

    this.items[pos].title = this.items[pos].title + ' [updated]'; 
    console.log('after update'); 
    console.log(this.items[pos]); 
    } 
}); 
+4

ファンタスティック、説明されている:あなたのケースでは

は、これを変更してみてください?この情報は金です:) – ghiscoding

関連する問題