这是使用自定义“可取消”绑定行为的替代方法。绑定会做这些事情:
- 拦截
updateSource 以将写入重定向到隐藏存储
- 侦听保存事件以将隐藏存储写回原始源。
"2" 是按照在绑定上下文中观察 saved 属性的约定完成的。如果需要更大的灵活性,可以将属性名称作为参数传递给自定义绑定。
app.html
<template>
<require from='./cancellable'></require>
<div>
Name: ${name}
Age: ${age}
<button click.delegate="edit()">Edit</button>
</div>
<div if.bind="editing">
<h3>Cancellable edit</h3>
Name: <input value.bind="name & cancellable">
Age: <input value.bind="age & cancellable">
<div><button click.delegate="save()">Save</button>
<button click.delegate="cancel()">Cancel</button></div>
</div>
<div if.bind="editing">
<h3>Instant edit</h3>
Name: <input value.bind="name">
Age: <input value.bind="age">
</div>
</template>
app.js
export class App {
constructor() {
this.name = 'John';
this.age = 20;
this.editing = false;
this.saved = false;
}
edit() {
this.saved = false;
this.editing = true;
}
save() {
this.saved = true;
this.editing = false;
}
cancel() {
this.saved = false;
this.editing = false;
}
}
cancellable.js
import {inject} from 'aurelia-dependency-injection';
import {BindingEngine} from 'aurelia-binding';
@inject(BindingEngine)
export class CancellableBindingBehavior {
constructor(bindingEngine) {
this.bindingEngine = bindingEngine;
}
bind(binding, scope) {
let value;
let modified = false;
let cancellable = {
originalUpdateSource: binding.updateSource,
originalUpdateTarget: binding.updateTarget,
};
// 1. Intercept "updateSource" to redirect write to a hidden value storage
binding.updateSource = (val) => {
value = val;
modified = true;
};
// 2. Intercept updateTarget" so that can observe change from original source
binding.updateTarget = (val) => {
value = val;
modified = false;
cancellable.originalUpdateTarget.call(binding, val);
}
// 3. Observe the "saved" event to copy back to original source
let bindingContext = scope.bindingContext;
cancellable.subscription = this.bindingEngine.propertyObserver(bindingContext, 'saved')
.subscribe((newValue, oldValue) => {
if (newValue && modified) {
cancellable.originalUpdateSource.call(binding, value);
}
});
binding.cancellable = cancellable;
}
unbind(binding, scope) {
binding.updateSource = binding.cancellable.originalUpdateSource;
binding.updateTarget = binding.cancellable.originalUpdateTarget;
binding.cancellable.subscription.dispose();
binding.cancellable = null;
}
}
要点跑:https://gist.run/?id=2c7e40e88d1d3c18e9d2bca6be438b47
参考:内置throttle binding behavior