如敲除官方文档所述(The data-bind syntax),绑定具有名称和值:
<span data-bind="name: value"></span>
?可以使用变量动态设置 name 部分吗?
eval
在这里不起作用。
背景: 我有一堆属性,可以是常规文本,URL,电话号码,isbn等。我还为其中一些属性定制了绑定,因此我需要为每个应用最适合的绑定...以编程方式
//viewmodel props
this.url1 = ko.observable(...);
this.text1 = ko.observable(...);
this.isbn1 = ko.observable(...);
...
var metaProps = [
{ name: 'url1', binding: 'url' },
{ name: 'text1', binding: 'text' },
{ name: 'isbn1', binding: 'isbn' },
...
]
这里的关键是我的viewmodel的道具取决于模型对象的特定子类型,因此我不想为每个子类型(太多)实现自定义HTML模板。现在,我的模板如下:
//HTML
<div data-bind='foreach: { data: metaProps }'>
<!-- ko if: binding == 'url' -->
<span data-bind="url: $parent[name]">
<!-- /ko -->
<!-- ko if: binding == 'isbn' -->
<span data-bind="isbn: $parent[name]">
<!-- /ko -->
<!-- ko if: binding == 'text' -->
<span data-bind="text: $parent[name]">
<!-- /ko -->
...
</div>
我的目标是将html简化为:
<div data-bind='foreach: { data: metaProps }'>
<span data-bind="binding: $parent[name]">
</div>
答案 0 :(得分:3)
有一个(很少有文档证明)实用程序功能applyBindingsToNode
,它允许您创建一个自定义绑定,该绑定可能会执行您想要的操作:
ko.bindingHandlers.dynamicBinding = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var bindings = {};
var bindingData = valueAccessor();
bindings[bindingData['binding']] = bindingContext.$data[bindingData['name']];
ko.applyBindingsToNode(element, bindings, bindingContext);
}
};
并这样称呼它:
<div data-bind="foreach: { data: metaProps, as: 'metaProp' }">
<span data-bind="dynamicBinding: metaProp"></span>
</div>
我喜欢@Tomalak所建议的组件概念,因为它允许标记的更大灵活性。一个小例子来演示:
要注册组件:
ko.components.register('isbn', {
viewModel: function(params) {
this.content = params.content;
},
template: '<span data-bind="text: content"></span>'
});
ko.components.register('url', {
viewModel: function(params) {
this.content = params.content;
},
template: '<a data-bind="attr: { href: content }, text: content"></a>'
});
稍微编辑您的metaProps对象,以便命名更清晰:
var metaProps = [
{ content: this.url1, component: 'url' },
{ content: this.text1, component: 'text' },
{ content: this.isbn1, component: 'isbn' },
...
]
然后调用component
绑定以加载组件。
<div data-bind="foreach: { data: metaProps, as: 'metaProp' }">
<!-- ko component: { name: metaProp.component, params: { content: metaProp.content } } -->
<!-- /ko -->
</div>
答案 1 :(得分:3)
我会与templates合作,因为:
<span>
,每个模板都可以不同。isbn
。它甚至可以完全取代对ISBN的自定义绑定处理程序的需求。
// as a mockup of your real "isbn" handler let's just use "text"
ko.bindingHandlers.isbn = ko.bindingHandlers.text;
ko.applyBindings({
metaProps: [
{type: 'text', value: 'Some sample text'},
{type: 'isbn', value: '978-1491914311'},
{type: 'url', value: 'https://knockoutjs.com/documentation/introduction.html', text: 'Knockout Docs'}
]
});
.isbn {font-family: monospace;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach: metaProps">
<div data-bind="template: 'template-' + type"></div>
</div>
<script type="text/html" id="template-text">
<span data-bind="text: value"></span>
</script>
<script type="text/html" id="template-isbn">
<span class="isbn" data-bind="isbn: value"></span>
</script>
<script type="text/html" id="template-url">
<a data-bind="attr: {href: value}, text: text"></a>
</script>
如果您更喜欢components,那是另一种选择。
答案 2 :(得分:0)
不确定这是否可以解决您的完整问题,但可以动态生成html。
function VM(){
var self = this;
self.metaProps = [
{ name: 'url1', val: '<a href="https://google.com">url</a>' },
{ name: 'text1', val: 'text' },
{ name: 'isbn1', val: 'isbn' },
]
}
ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-bind="foreach:metaProps">
<span data-bind="html:val"><br/>
</div>