我目前正在使用事件绑定来格式化电话号码(转换为xxx-xxx-xxxx格式),我想创建一个可重复使用的自定义绑定,以便将来在我们的应用中使用。当前事件绑定工作正常,但我无法使自定义绑定正常工作。任何人都可以看看下面并告诉我我的问题吗?
使用viewModel方法绑定当前事件:
<input class="form-control" id="Phone" type="text"
data-bind="event: {blur: formatPhone}, enable: isInputMode, value: Phone" />
self.Phone = ko.observable(model.MainPhone).extend({ maxLength: 20 });
self.formatMainPhone = function() {
var tempString = self.Phone().replace(/\D+/g, "").replace(/^[01]/, "").replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3").substring(0, 12);
self.Phone(tempString);
}
不起作用的自定义绑定处理程序:
<input class="form-control max225" id="Phone" type="text"
data-bind="formatPhoneNumber: Phone, enable: isInputMode, value: Phone" />
self.Phone = ko.observable(model.MainPhone).extend({ maxLength: 20 });
ko.bindingHandlers.formatPhoneNumber = {
update: function (element, valueAccessor) {
var phone = ko.utils.unwrapObservable(valueAccessor());
var formatPhone = function () {
return phone.replace(/\D+/g, "").replace(/^[01]/, "").replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3").substring(0, 11);
}
ko.bindingHandlers.value.update(element, formatPhone);
}
};
答案 0 :(得分:0)
您的绑定试图劫持默认“值”绑定的更新,该绑定查看了淘汰源代码,似乎已被弃用。
'update': function() {} // Keep for backwards compatibility with code that may have wrapped value binding
您必须更改绑定,以便它使用init。
ko.bindingHandlers.value.init(element, formatPhone, allBindings);
编辑:
这可能更接近你想要的。而不是使用更新绑定,这将创建一个中间计算observable,然后使用value.init将文本框绑定到该。我们永远不需要更新绑定,因为计算将负责为您传播更改。
ko.bindingHandlers.formatPhoneNumber = {
init: function (element, valueAccessor, allBindings) {
var source = valueAccessor();
var formatter = function(){
return ko.computed({
read: function(){ return source(); },
write: function(newValue){
source(newValue.replace(/\D+/g, "").replace(/^[01]/, "").replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3").substring(0, 12));
}
})
};
ko.bindingHandlers.value.init(element, formatter, allBindings);
}
};
编辑2 - 更多解释
使用formatPhoneNumber的更新绑定告诉knockout在值发生变化时运行该代码。这在理论上听起来不错,但让我们把它分解。
因为这是一个更新绑定,所以在步骤1中展开访问者会创建一个触发器,以便在访问者值发生更改时重新评估绑定。然后在第3步中,你告诉knockout重新执行value.update绑定,它当前只是一个空函数,什么都不做。如果你改变它来使用value.init而事实上可能实际上用于格式化输出,但是你告诉knockout每次值改变时重新初始化init绑定。
update: function(element, valueAccessor, allBindings) {
var phone = ko.utils.unwrapObservable(valueAccessor());
var formatPhone = function() { return phone.replace(...)}
ko.bindingHandlers.value.init(element, formatPhone, allBindings);
}
重新创建绑定并传递新的初始值。这也意味着它只是一个单向绑定,因为对前端的更改无法返回到模型以更新后备可观察对象。
现在,如果您将自己的绑定更改为init绑定,并从那里调用value.init绑定,它只会被初始化一次,但下一个问题是您绑定的函数isn'我会知道何时更新。
init: function(element, valueAccessor, allBindings) {
var phone = ko.utils.unwrapObservable(valueAccessor());
var formatPhone = function() { return phone.replace(...)}
ko.bindingHandlers.value.init(element, formatPhone, allBindings);
}
由于它只是一个正常的js函数,它正在传递一个已经解开的平坦值,它总是会根据手机的原始值给出相同的结果。传递value.init绑定计算的observable,确保对accessor observable的更新触发format函数从现有绑定中更新。