如何在 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]);
  }
});