2016-04-04 17 views
8

Ich beginne mit einer einfachen TODO App mit Aurelia, RethinkDB & Socket.IO. Ich habe Probleme mit der Neuberechnung oder Neubewertung eines Objekts, das über Socket.IO geändert wurde. Im Prinzip läuft also alles gut auf dem ersten Browser, wird aber nicht im zweiten Browser neu gerendert, während das Objekt in der Konsole Unterschiede in meinem Objekt anzeigt. Das Problem besteht nur darin, ein Objekt zu aktualisieren, es funktioniert perfekt beim Erstellen/Löschen von Objekten aus dem Array von Todo-Objekten.Wie erzwingen verbindliche Neubewertung oder Neu-Rendering in Aurelia

HTML

<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 mit RethinkDB changefeeds

// 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); 
    }); 

Socket.on beobachten Aurelia Code

// 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); 
    } 
}); 

Die socket.on("todo_update", ...){} nicht den zweiten Browser neu rendern zu machen, aber das zeigt, Objekt in der Konsole vor/nach dem Update zeigt Unterschiede im Objekt selbst. Ich habe sogar die Todo-Titel-Eigenschaft geändert, und auch das wird nicht neu gerendert.

Wie kann ich Aurelia in meinem zweiten Browser mit den neuen Objekteigenschaften neu rendern? Sei nicht zu hart zu mir, ich lerne Aurelia/RethinkDB/NodeJS/Socket.IO alle gleichzeitig ...

Antwort

16

Aurelia beobachtet Änderungen am Inhalt eines Arrays durch Überschreiben der Mutator-Methoden des Arrays (Push , Pop, Spleiß, Schicht, usw.). Dies funktioniert gut für die meisten Anwendungsfälle und funktioniert sehr gut (keine Dirty-Checking, extrem leicht in Bezug auf Speicher und CPU). Leider bleibt eine Möglichkeit übrig, ein Array zu mutieren, das Aurelia nicht "sehen" kann: indexierte Zuweisung ... zB myArray[6] = 'foo'. Da keine Array-Methoden aufgerufen wurden, weiß das Bindungssystem nicht, dass das Array geändert wurde.

In Ihrem Fall versuchen, diese zu ändern:

// 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

Fantastisch, die Erklärung ist genau das, was ich wollte von Änderungen, dass Dokument irgendwo kenne und bleibe aus schmutziger Prü ... ist? Diese Information ist Gold :) – ghiscoding