在Aurelia

时间:2016-07-14 22:20:28

标签: javascript aurelia aurelia-binding

我正在构建一个拖放工作区,类似于您制作模型的工作区。我有一个工作区自定义元素,它有一个更大的嵌套元素,可以缩放和平移。因此,我需要仔细跟踪工作空间的大小和位置数据以及所有包含的元素。

在我的自定义元素的附加事件中,我以编程方式将工作空间的高度和宽度设置为JavaScript对象,该对象绑定到视图中的css:

workspaceCustomElement.js

export class WorkspaceCustomElement {

    constructor(element) {
        this.element = element;
    }

    attached() {
        this.workspace.size = {
            height: this.element.height * 5,
            width: this.element.width * 5
        }
    }
}

workspaceCustomElement.html

<div css="height: ${workspace.height}px; width: ${workspace.width}px; 
    left: ${(element.clientWidth - workspace.width)/2}px; 
    top: ${(element.clientHeight - workspace.height)/2}px;"></div>

现在我遇到了试图抓住我孩子元素位置的问题。我也在它们上附加了回调函数,但它们正在之前上面附加的回调中进行评估,因此css绑定尚未被评估,并且大小和位置都是错误的。

我需要在评估attached()之后添加回调,并且绑定已经更新。我可以使用{{1}来完成此操作黑客,但我不相信这将永远有效。

setTimeout

在下次绑定更新后,是否有更好,更可靠的方法对指令进行排队?

2 个答案:

答案 0 :(得分:4)

最佳做法是向TaskQueue添加任务。在引擎盖下,绑定引擎使用TaskQueue本身,因此添加新任务会将其排在绑定更新后面。

<强> workspaceCustomElement.js

export class WorkspaceCustomElement {

    constructor(element, queue) {
        this.element = element;
        this.queue = queue;
    }

    attached() {
        this.workspace.size = {
            height: this.element.height * 5,
            width: this.element.width * 5
        }
        this.queue.queueMicroTask(() => {
            let components = this.element.querySelectorAll('.component');
            Array.prototype.forEach.call(components, (component) => {
                let model = component.model;
                model.position = { 
                    x: component.clientLeft,
                    y: component.clientTop
                };
            }
        });
    }
}

有关详细信息,请参阅此处:TaskQueue API

答案 1 :(得分:3)

您可以创建一个绑定行为,只要绑定更新目标(DOM元素/ custom-element / custom-attribute),就会调用您选择的回调。

以下是一个示例:https://gist.run?id=28c0fedb21b5d8100913d3bc5500499f

<强>目标updated.js

export class TargetUpdatedBindingBehavior {
  bind(binding, source, callback) {
    // override the binding's updateTarget method.  add logic to invoke
    // the callback passed as a parameter to the binding behavior.
    binding.standardUpdateTarget = binding.updateTarget;
    binding.targetUpdatedCallback = callback;
    binding.updateTarget = function(value) {
      this.standardUpdateTarget(value);
      this.targetUpdatedCallback(this.target, this.targetProperty, value);
    };
  }

  unbind(binding, source) {
    // revert the binding to it's original state.
    binding.updateTarget = binding.standardUpdateTarget;
    binding.standardUpdateTarget = null;
    binding.targetUpdatedCallback = null;
  }
}

http://aurelia.io/hub.html#/doc/article/aurelia/binding/latest/binding-binding-behaviors

@MathewJamesDavis的答案是完全有效的,我只是提供这个作为第二选择。