Knockout custom element是否可以将params属性绑定到像Component binding这样的对象?
例如,我定义了以下组件:
ko.components.register('user-widget', {
template: '<p><span data-bind = "text:fullName" ></span></p>',
viewModel: function (params) {
this.fullName = params.firstName + ' ' + params.lastName;
}
});
以下VM:
function VM() {
this.user = {
firstName: 'Joe',
lastName: 'Baker'
};
}
使用组件绑定时,我可以将VM的用户属性直接传递给params属性,如下所示:
<div data-bind='component:{name:"user-widget", params:user}'></div>
但是,当使用自定义元素时,我必须像这样取消用户属性:
<user-widget params="firstName:user.firstName, lastName:user.lastName"></user-widget>
我尝试使用带有组件绑定的自定义元素,如下所示:
<user-widget data-bind='component:{params:user}'></user-widget>
导致以下错误:
无法使用&#34;组件&#34;绑定到匹配a的自定义元素 成分
答案 0 :(得分:5)
您需要更改组件以接受用户参数,而不是每个单独的参数。
<user-widgetx params='user: user'></user-widgetx>
ko.components.register('user-widgetx', {
template: '<p><span data-bind = "text:fullName" ></span></p>',
viewModel: function (params) {
this.fullName = params.user.firstName + ' ' + params.user.lastName;
}
});
我探索了调整绑定提供程序以挂钩解析代码的想法。我能够把事情搞定。但我必须警告你,这无论如何都是黑客攻击。这是使用Knockout v3.2测试,我不保证这将始终有效。至少,直到他们以其他方式添加以扩展淘汰赛的核心功能。
查看源代码,我注意到params
解析代码正在使用knockout的内置绑定解析器。因此,如果我们可以以某种方式挂钩解析器,我们可以调整绑定字符串的解释方式以实现我们想要的。
这里的目标是创建一种新类型的绑定,以便将解析后的表达式视为实际绑定对象。这也可以在组件参数之外进一步使用。这样,我们可以在bindings / params中执行此操作:
<user-widget params='${user}'></user-widget>
现在${ }
内的任何内容都可以被视为绑定/参数对象。
(function () {
var originalParseBindingsString = ko.bindingProvider.prototype.parseBindingsString,
re = /^\$\{(.+)\}$/;
function extractBindableObject(objExpr, bindingContext, node, options) {
var objBindingString = '_object: ' + objExpr,
objGetter = originalParseBindingsString.call(this, objBindingString, bindingContext, node, options),
obj = objGetter['_object']();
return objectMap(obj, function (value) {
return function () { return value; };
});
}
function objectMap(obj, mapper) {
if (!obj) return obj;
var result = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop))
result[prop] = mapper(obj[prop], prop, obj);
}
return result;
}
ko.bindingProvider.prototype.parseBindingsString = function (bindingsString, bindingContext, node, options) {
var m = bindingsString.match(re);
if (m) {
return extractBindableObject.call(this, m[1], bindingContext, node, options);
}
return originalParseBindingsString.apply(this, arguments);
};
}());
答案 1 :(得分:0)
如果有人来这里寻找解决此问题的方法,我会这样解决:
注册组件时,使您的函数viewmodel构造函数仅用于接收包含所需所有参数的整个对象:
function gridViewModel(params) {
var self = this;
var gridConfig = params.gridConfig;
self.data = gridConfig.data;
self.currentPageIndex = ko.observable(0);
self.pageSize = gridConfig.pageSize || 5;
...
}
ko.components.register("grid-widget", {
template: { element: 'ko-grid'},
viewModel: gridViewModel
});
然后,您可以像这样使用自定义元素:
<grid-widget params='gridConfig: gridConfig'></grid-widget>
第一个 gridConfig 是构造函数将在其上接收的参数
params.gridConfig ,第二个是您在最近的viewModel上下文中拥有的对象。