如何在 Aurelia 中强制绑定 re-evaluate 或 re-rendering
How to force binding re-evaluate or re-rendering in Aurelia
我开始使用 Aurelia、RethinkDB 和 Socket.IO 的简单 TODO 应用程序。我似乎对通过 Socket.IO 更改的 re-rendering 或 re-evaluating 和 object 有疑问。所以基本上,在第一个浏览器上一切正常,但在第二个浏览器中没有得到 re-rendered,而在控制台中显示 object 确实显示了我的 object 中的差异。问题仅在于更新 object,它在待办事项数组的 creating/deleting object 上完美运行。
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>
带有 RethinkDB 变更源的 NodeJS
// 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);
});
Aurelia 正在看代码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", ...){}
没有使第二个浏览器 re-render 但在控制台中显示 object before/after 更新确实显示了 object 本身的差异.我什至更改了待办事项标题 属性,但也没有得到 re-rendered。
如何使用新的 object 属性在我的第二个浏览器中将 Aurelia 设置为 re-render?不要对我太苛刻,我一直在学习 Aurelia/RethinkDB/NodeJS/Socket.IO...
Aurelia 通过覆盖数组的修改器方法(push、pop、splice、shift 等)来观察数组内容的变化。这适用于大多数用例并且性能非常好(没有脏检查,在内存和 cpu 方面非常轻量级)。不幸的是,这留下了一种改变 aurelia 不能 "see" 的数组的方法:索引赋值...例如 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]);
}
});
我开始使用 Aurelia、RethinkDB 和 Socket.IO 的简单 TODO 应用程序。我似乎对通过 Socket.IO 更改的 re-rendering 或 re-evaluating 和 object 有疑问。所以基本上,在第一个浏览器上一切正常,但在第二个浏览器中没有得到 re-rendered,而在控制台中显示 object 确实显示了我的 object 中的差异。问题仅在于更新 object,它在待办事项数组的 creating/deleting object 上完美运行。
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>
带有 RethinkDB 变更源的 NodeJS
// 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);
});
Aurelia 正在看代码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", ...){}
没有使第二个浏览器 re-render 但在控制台中显示 object before/after 更新确实显示了 object 本身的差异.我什至更改了待办事项标题 属性,但也没有得到 re-rendered。
如何使用新的 object 属性在我的第二个浏览器中将 Aurelia 设置为 re-render?不要对我太苛刻,我一直在学习 Aurelia/RethinkDB/NodeJS/Socket.IO...
Aurelia 通过覆盖数组的修改器方法(push、pop、splice、shift 等)来观察数组内容的变化。这适用于大多数用例并且性能非常好(没有脏检查,在内存和 cpu 方面非常轻量级)。不幸的是,这留下了一种改变 aurelia 不能 "see" 的数组的方法:索引赋值...例如 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]);
}
});