将逻辑从视图移动到自定义绑定
Moving logic from the view to a custom binding
我创建了一个 Knockout 扩展程序,因此我可以轻松地将我的表单字段恢复为它们的原始值。
我想从我的视图中剔除混乱,所以我想改变它:
<div data-bind="if: myObservedValue.hasChanges">
<a href="#" data-bind="click: myObservedValue.revert">Revert</a>
</div>
变成这样的东西:
<a href="#" data-bind="revert: myObservedValue">Revert</a>
我知道我需要创建一个自定义绑定,但我正在努力寻找一种干净的方法来:
- 仅将我的可观察对象传递给我的绑定并在内部应用可见绑定(考虑我的可观察对象扩展是否有变化)
- 合并多个绑定,因为我的 'revert' 绑定需要使用 'click' 和 'visible' 绑定
- 避免将恢复功能暴露在我的视图中
提前致谢
ko.extenders.revert = function(target, option) {
target.revert = function() {
target(target.previousValue);
target.hasChanges(false);
};
target.previousValue = option;
target.hasChanges = ko.observable(false);
target.hasChanges.extend({
rateLimit: 100
});
target.subscribe(function(newValue) {
target.hasChanges(target() != target.previousValue);
});
return target;
};
var Vm = function(initialValue) {
this.myObservedValue = ko.observable(initialValue).extend({
revert: initialValue
});
this.revert = function() {
this.revert();
}.bind(this.myObservedValue);
return {
myObservedValue: this.myObservedValue,
revert: this.revert
}
}
ko.applyBindings(new Vm('Edit me!!!'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: myObservedValue" />
<div data-bind="if: myObservedValue.hasChanges">
<a href="#" data-bind="click: myObservedValue.revert">Revert</a>
</div>
您可以使用 applyBindingsToNode 函数来包装其他绑定
ko.extenders.revert = function(target, option) {
target.revert = function() {
target(target.previousValue);
target.hasChanges(false);
};
target.previousValue = option;
target.hasChanges = ko.observable(false);
target.hasChanges.extend({
rateLimit: 100
});
target.subscribe(function(newValue) {
target.hasChanges(target() != target.previousValue);
});
return target;
};
var Vm = function(initialValue) {
this.myObservedValue = ko.observable(initialValue).extend({
revert: initialValue
});
this.revert = function() {
this.revert();
}.bind(this.myObservedValue);
return {
myObservedValue: this.myObservedValue,
revert: this.revert
}
}
ko.bindingHandlers["revert"] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var obs = valueAccessor();
ko.applyBindingsToNode(element, { visible: obs.hasChanges, click: obs.revert });
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
}
}
ko.applyBindings(new Vm('Edit me!!!'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: myObservedValue" />
<a href="#" data-bind="revert: myObservedValue">Revert</a>
也可以通过包装 textInput 绑定来完全摆脱锚点
var oldTextInputInit = ko.bindingHandlers["textInput"].init;
ko.bindingHandlers["textInput"].init = function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var obs = valueAccessor();
if (obs.revert && obs.hasChanges) {
var a = element.ownerDocument.createElement('a');
a.href = '#';
if ( element.nextSibling ) {
element.parentNode.insertBefore(a, element.nextSibling);
} else {
element.parentNode.appendChild(a);
}
ko.applyBindingsToNode( a, { text: 'Revert', visible: obs.hasChanges, click: obs.revert });
}
return oldTextInputInit(element, valueAccessor, allBindings, viewModel, bindingContext);
}
您还可以向覆盖的 textInput 绑定读取的输入添加另一个自定义绑定,这样您就可以传递模板名称来控制要添加的其他 HTML,等等
我创建了一个 Knockout 扩展程序,因此我可以轻松地将我的表单字段恢复为它们的原始值。
我想从我的视图中剔除混乱,所以我想改变它:
<div data-bind="if: myObservedValue.hasChanges">
<a href="#" data-bind="click: myObservedValue.revert">Revert</a>
</div>
变成这样的东西:
<a href="#" data-bind="revert: myObservedValue">Revert</a>
我知道我需要创建一个自定义绑定,但我正在努力寻找一种干净的方法来:
- 仅将我的可观察对象传递给我的绑定并在内部应用可见绑定(考虑我的可观察对象扩展是否有变化)
- 合并多个绑定,因为我的 'revert' 绑定需要使用 'click' 和 'visible' 绑定
- 避免将恢复功能暴露在我的视图中
提前致谢
ko.extenders.revert = function(target, option) {
target.revert = function() {
target(target.previousValue);
target.hasChanges(false);
};
target.previousValue = option;
target.hasChanges = ko.observable(false);
target.hasChanges.extend({
rateLimit: 100
});
target.subscribe(function(newValue) {
target.hasChanges(target() != target.previousValue);
});
return target;
};
var Vm = function(initialValue) {
this.myObservedValue = ko.observable(initialValue).extend({
revert: initialValue
});
this.revert = function() {
this.revert();
}.bind(this.myObservedValue);
return {
myObservedValue: this.myObservedValue,
revert: this.revert
}
}
ko.applyBindings(new Vm('Edit me!!!'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: myObservedValue" />
<div data-bind="if: myObservedValue.hasChanges">
<a href="#" data-bind="click: myObservedValue.revert">Revert</a>
</div>
您可以使用 applyBindingsToNode 函数来包装其他绑定
ko.extenders.revert = function(target, option) {
target.revert = function() {
target(target.previousValue);
target.hasChanges(false);
};
target.previousValue = option;
target.hasChanges = ko.observable(false);
target.hasChanges.extend({
rateLimit: 100
});
target.subscribe(function(newValue) {
target.hasChanges(target() != target.previousValue);
});
return target;
};
var Vm = function(initialValue) {
this.myObservedValue = ko.observable(initialValue).extend({
revert: initialValue
});
this.revert = function() {
this.revert();
}.bind(this.myObservedValue);
return {
myObservedValue: this.myObservedValue,
revert: this.revert
}
}
ko.bindingHandlers["revert"] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var obs = valueAccessor();
ko.applyBindingsToNode(element, { visible: obs.hasChanges, click: obs.revert });
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
}
}
ko.applyBindings(new Vm('Edit me!!!'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: myObservedValue" />
<a href="#" data-bind="revert: myObservedValue">Revert</a>
也可以通过包装 textInput 绑定来完全摆脱锚点
var oldTextInputInit = ko.bindingHandlers["textInput"].init;
ko.bindingHandlers["textInput"].init = function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var obs = valueAccessor();
if (obs.revert && obs.hasChanges) {
var a = element.ownerDocument.createElement('a');
a.href = '#';
if ( element.nextSibling ) {
element.parentNode.insertBefore(a, element.nextSibling);
} else {
element.parentNode.appendChild(a);
}
ko.applyBindingsToNode( a, { text: 'Revert', visible: obs.hasChanges, click: obs.revert });
}
return oldTextInputInit(element, valueAccessor, allBindings, viewModel, bindingContext);
}
您还可以向覆盖的 textInput 绑定读取的输入添加另一个自定义绑定,这样您就可以传递模板名称来控制要添加的其他 HTML,等等