我正在构建一个拖放工作区,类似于您找到的用于制作模型的工作区。我有一个工作区自定义元素,该元素具有可以缩放和平移的较大嵌套元素。因此,我需要仔细跟踪工作区和所有包含元素的大小和位置数据。
在自定义元素的附加事件中,我以编程方式将工作区的高度和宽度设置为 JavaScript 对象,该对象绑定到视图中的 css:
工作区自定义元素.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()
并更新绑定后添加回调。我可以通过使用setTimeout
黑客来实现这一点,但我不相信这将永远有效。
attached() {
this.workspace.size = {
height: this.element.height * 5,
width: this.element.width * 5
}
setTimeout(() => {
let components = this.element.querySelectorAll('.component');
Array.prototype.forEach.call(components, (component) => {
let model = component.model;
model.position = {
x: component.clientLeft,
y: component.clientTop
};
}
}, 0)
}
有没有更好、更可靠的方法在下一次绑定更新后对指令进行排队?
最佳做法是将任务添加到TaskQueue
。在后台,绑定引擎使用TaskQueue
本身,因此添加新任务会将其排在绑定更新后面。
工作区自定义元素.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
};
}
});
}
}
有关详细信息,请参阅此处:任务队列 API
您可以创建一个绑定行为,每当绑定更新目标(DOM 元素/自定义元素/自定义属性)时,都会调用您选择的回调。
下面是一个示例:https://gist.run?id=28c0fedb21b5d8100913d3bc5500499f
目标已更新.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的回答是完全有效的,我只是将其作为第二种选择。