如何将事件数据从阶段传递到父上下文而不解构/重构它?

时间:2013-01-21 21:26:22

标签: bonsaijs

考虑以下代码:

window.stage = bonsai.run(document.getElementById('stage'), {
  code: function() {
    var circle;
    circle = new Circle(200, 200, 50);
    circle.stroke('green', 2);
    circle.addTo(stage);
    circle.on('click', function(ev) {
      stage.sendMessage('click', ev);
    });
  },
  width: 500,
  height: 500
});

stage.on('load', function() {
  console.log('loaded');
  stage.on('message:click', function(ev) {
      console.log('click', ev);
  });
});

因此,点击圈子会出现错误: DATA_CLONE_ERR:DOM例外25

如果我发送像ev.x和ev.y这样的属性,它们会传出正常的结果。我也可以在发送之前从其属性重建对象,并且传递正常。

如何将事件对象完整地发送到父上下文而不解构 - >重建它?顺便说一句,盆景为什么会这样工作?

1 个答案:

答案 0 :(得分:2)

很好,你已经问过为什么我们这样做了分离。刚刚浏览了BonsaiJS文档并意识到我们没有明确说出为什么我们将渲染与执行线程分开。

BonsaiJS代码主要在工作程序中执行(如果工作程序不可用,则返回iframe)并使用postMessage与创建工作程序的上下文进行通信。引发DATA_CLONE_ERR: DOM Exception 25是因为postMessage无法序列化DOM事件对象。要解决您的问题,您可以创建一个简单的函数,它删除对象的所有嵌套对象/函数,应该传递:

window.stage = bonsai.run(document.getElementById('stage'), {
  code: function() {
    var circle;
    var makeSerializable = function(obj) {
      var ret = {}, val;
      Object.keys(obj).forEach(function(key) {
        val = obj[key];
        if (typeof val != 'object' && typeof val != 'function') {
          ret[key] = val;
        };
      });
      return ret; 
    };
    circle = new Circle(200, 200, 50);
    circle.stroke('green', 2);
    circle.addTo(stage);
    circle.on('click', function(ev) {
      stage.sendMessage('click', makeSerializable(ev));
    });
  },
  width: 500,
  height: 500
});

stage.on('load', function() {
  console.log('loaded');
  stage.on('message:click', function(ev) {
    console.log('click', ev);
  });
});

或者你可以强制BonsaiJS在iFrame中执行。然后你就可以访问DOM了,你可以序列化任何对象(注意:见下文,为什么我不建议这样做):

window.stage = bonsai.setup({
  runnerContext: bonsai.IframeRunnerContext
}).run({...});

将主代码执行放入worker的主要原因是,我们不希望任何计算阻止渲染“线程”,以便我们获得更流畅的动画(如果代码在iFrame中执行)渲染+代码执行将在同一个线程中发生,并且不会像工作者那样流畅。在worker中执行JS代码的另一个好处是,我们不依赖于DOM,也可以使用相同的JS代码并在不同的JS环境中执行它,如Rhino或NodeJS(这里是一些示例代码,如何使用可以在节点上执行BonsaiJS并通过SocketIO将呈现消息发送到浏览器:https://github.com/uxebu/bonsai-server)。