Bri*_*unt 6 knockout.js knockout-es5-plugin knockout-3.0
我有一个Knockout扩展,knockout-secure-binding,我们遇到了一个问题.
特别是在使用时Object.defineProperty
,如knockout-es5所做的那样,当在一个触发更改事件时,不会调用value
绑定的update
函数input
.
我的单元测试说明了它的特殊性.这有效:
it("reads an input `value` binding", function () {
var input = document.createElement("input"),
evt = new CustomEvent("change"),
context = { vobs: ko.observable() };
input.setAttribute("data-sbind", "value: vobs")
ko.applyBindings(context, input)
input.value = '273-9164'
input.dispatchEvent(evt)
assert.equal(context.vobs(), '273-9164')
})
Run Code Online (Sandbox Code Playgroud)
这(敲除-s5定义属性的方式)不起作用:
it("reads an input `value` binding for a defineProperty", function () {
// see https://github.com/brianmhunt/knockout-secure-binding/issues/23
var input = document.createElement("input"),
evt = new CustomEvent("change"),
obs = ko.observable(),
context = { };
Object.defineProperty(context, 'pobs', {
configurable: true,
enumerable: true,
get: obs,
set: obs
});
input.setAttribute("data-sbind", "value: pobs")
ko.applyBindings(context, input)
input.value = '273-9164'
input.dispatchEvent(evt)
assert.equal(context.pobs, '273-9164')
})
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,如上所述,value.update
在调用时不会被input.dispatchEvent
调用.
自定义绑定返回自己的valueAccessor
,所以我希望问题与此相关.它只是让我觉得特别奇怪,它可以使用对象属性,但不是defineProperty
.
Knockout在处理它们之前会重写绑定事务,以便支持"双向绑定以包含允许处理程序更新值的写入函数,即使它不是可观察的值".此部分使Object.defineProperty
定义的属性在绑定中起作用.
这是在ko.expressionRewriting.preProcessBindings
方法(源)中实现的
此方法将转换以下绑定表达式:
data-bind="value: pobs, checked: vobs"
Run Code Online (Sandbox Code Playgroud)
以下内容:
"'value':function(){return pobs },'checked':function(){return vobs },'_ko_property_writers':function(){return {'value':function(_z){pobs=_z},'checked':function(_z){vobs=_z}} }"
Run Code Online (Sandbox Code Playgroud)
请注意生成的_ko_property_writers
内容包含用于设置不可观察的proeprties的代码.
以下是有关此魔术属性的源代码注释:
// For those developers who rely on _ko_property_writers in their custom bindings, we expose _twoWayBindings as an
// undocumented feature that makes it relatively easy to upgrade to KO 3.0. However, this is still not an official
// public API, and we reserve the right to remove it at any time if we create a real public property writers API.
Run Code Online (Sandbox Code Playgroud)
因此,您只需要在convert_to_accessors
函数中重现相同的逻辑:您需要在result
名为的对象上创建一个新属性,该属性将"_ko_property_writers"
返回相应的编写器函数:
Parser.prototype.convert_to_accessors = function (result) {
var propertyWriters = {};
ko.utils.objectForEach(result, function (name, value) {
if (value instanceof Identifier || value instanceof Expression) {
result[name] = function expidAccessor() {
// expression or identifier accessir
return value.get_value();
};
if (ko.expressionRewriting.twoWayBindings[name]) {
var token = value.token;
var context = value.parser.context.$data;
propertyWriters[name] = function(_z) {
context[token] = _z;
};
}
} else if (typeof(value) != 'function') {
result[name] = function constAccessor() {
return value;
};
}
});
if (Object.keys(propertyWriters).length > 0)
result["_ko_property_writers"] = function () {
return propertyWriters;
}
return result;
};
Run Code Online (Sandbox Code Playgroud)
免责声明:这不是一个生产就绪的实施!它只是展示了需要做什么的想法.虽然它会进行两个示例测试,但它可能会破坏插件的其他部分.您还应该特别注意正确的上下文处理,因为使用value.parser.context.$data
有点hacky.
归档时间: |
|
查看次数: |
1008 次 |
最近记录: |