如何强制在Aurelia中重新评估或重新渲染绑定

ghi*_*ing 12 javascript sockets rethinkdb aurelia aurelia-binding

我开始使用Aurelia,RethinkDB和Socket.IO的简单TODO应用程序.我似乎在重新渲染或重新评估通过Socket.IO更改的对象时遇到问题.所以基本上,一切都在第一个浏览器上运行良好但在第二个浏览器中没有重新渲染,而在控制台中显示对象确实显示了我的对象的差异.问题仅在于更新对象时,它完全适用于从待办事项数组创建/删除对象.

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>
Run Code Online (Sandbox Code Playgroud)

带有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);
    });
Run Code Online (Sandbox Code Playgroud)

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);
  }
});
Run Code Online (Sandbox Code Playgroud)

socket.on("todo_update", ...){}不是让第二个浏览器重新渲染,但显示在控制台中的对象之前/更新并显示在对象本身的差异后.我甚至改变了todo title属性,也没有重新渲染.

如何让Aurelia在我的第二个浏览器中使用新的对象属性重新渲染?不要太难我,我同时学习Aurelia/RethinkDB/NodeJS/Socket.IO ......

Jer*_*yow 21

Aurelia通过覆盖数组的mutator方法(push,pop,splice,shift等)来观察数组内容的变化.这适用于大多数用例并且表现非常好(没有脏检查,在内存和CPU方面非常轻量级).不幸的是,这留下了一种改变aurelia无法"看到"的数组的方法:索引赋值...例如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]);
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 太棒了,解释正是我想要知道的并且不受肮脏的检查...这个文件是否因任何变化而存在?这个信息是金:) (4认同)