使用 Knockout 绑定到 return 字符串
Using Knockout bindings to return string
我正在尝试使用 Knockout 来更好地使用我正在使用的无限滚动插件,但在如何绑定它方面遇到了困难。不确定以当前形式是否可行。
滚动条调用一个数据函数,该函数通过 AJAX 加载下一个数据块。然后它调用一个工厂函数将该数据转换为 HTML,然后将 HTML 加载到容器中,并根据当前内容大小更新其内部状态。
我坚持认为它需要一个 HTML 字符串。
我想做的是:
<div class="scroller" data-bind="infiniteScroll: { get: loadItems }">
<div class="item">
<p>
<span data-bind="text:page"></span>
<span class="info" data-bind="text"></span>
</p>
</div>
</div>
我完全坚持的绑定是这个 - 目前只是对响应进行硬编码,显然 - 这是我需要用模板绑定替换的部分:
ko.bindingHandlers.infiniteScroll = {
init:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
if($.fn.infiniteScroll)
{
// Get current value of supplied value
var field = f_valueaccessor();
var val = ko.unwrap(field);
var options = {};
if(typeof(val.get) == 'function')
options = val;
else
options.get = val;
options.elementFactory = options.elementFactory ||
function(contentdata, obj, config)
{
var s = '';
for(var i = 0; i < contentdata.length; i++)
{
var o = contentdata[i];
// NEED TO REPLACE THIS
s += '<div class="item"><p>Item ' + o.page + '.' + i + ' <span class="info">' + o.text + '</span></p></div>';
}
return s;
};
$(el).infiniteScroll(options);
return { controlsDescendantBindings: true };
}
}
};
contentdata
是一个对象数组,例如[ { page:1, text:'Item1' }, { page:1, text:'Item2' } ... ]
调用之间的页面大小可能不同;我无法知道该服务将 return;它不是传统的页面,更像是下一个数据块。
所以在元素工厂中,我想以某种方式使用 .scroller
中的标记作为模板绑定 contentdata 数组,类似于 foreach,然后 return 该标记到滚动条插件。
请注意,我可以修改无限滚动源,所以如果不能用字符串完成,returning DOM 元素也可以。
我只是不知道如何 a) 使用内容作为模板,以及 b) return 将绑定结果绑定到插件以便它可以更新其状态。
注意:我最终打算使用的页面目前正在使用 foreach
非平凡对象模型;因此需要使用相同的标记;它需要大量更换。
在这个问题之后,我实际上已经找到了如何使用现有的滚动条来做到这一点:Jquery knockout: Render template in-memory
基本上,您使用 applyBindingsToNode(domelement, bindings)
,这会将 KO 绑定应用于节点集,重要的是不必连接到 DOM。
所以我可以将绑定元素中的标记存储为模板,然后将其清空,然后为元素工厂使用 jQuery 创建一个临时节点集,使用上述函数绑定它,然后 return HTML.
诚然,重构为使用纯 KO 滚动条可能会更好,但这意味着我可以继续使用经过测试和熟悉的插件,代码可能会对人们有所帮助,因为这似乎是一个很常见的问题主题。
这是绑定的新代码(标记如上)。
ko.bindingHandlers.infiniteScroll = {
init:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
if($.fn.infiniteScroll)
{
// Get current value of supplied value
var field = f_valueaccessor();
var val = ko.unwrap(field);
var options = {};
if(typeof(val.get) == 'function')
options = val;
else
options.get = val;
var template = $(el).html();
options.elementFactory = options.elementFactory ||
function(contentdata, obj, config)
{
// Need a root element for foreach to use as a container, as it removes the root element on binding.
var newnodes = $('<div>' + template + '</div>');
ko.applyBindingsToNode(newnodes[0], { foreach: contentdata });
return newnodes.html();
};
$(el)
.empty()
.infiniteScroll(options);
return { controlsDescendantBindings: true };
}
}
};
我正在尝试使用 Knockout 来更好地使用我正在使用的无限滚动插件,但在如何绑定它方面遇到了困难。不确定以当前形式是否可行。
滚动条调用一个数据函数,该函数通过 AJAX 加载下一个数据块。然后它调用一个工厂函数将该数据转换为 HTML,然后将 HTML 加载到容器中,并根据当前内容大小更新其内部状态。
我坚持认为它需要一个 HTML 字符串。
我想做的是:
<div class="scroller" data-bind="infiniteScroll: { get: loadItems }">
<div class="item">
<p>
<span data-bind="text:page"></span>
<span class="info" data-bind="text"></span>
</p>
</div>
</div>
我完全坚持的绑定是这个 - 目前只是对响应进行硬编码,显然 - 这是我需要用模板绑定替换的部分:
ko.bindingHandlers.infiniteScroll = {
init:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
if($.fn.infiniteScroll)
{
// Get current value of supplied value
var field = f_valueaccessor();
var val = ko.unwrap(field);
var options = {};
if(typeof(val.get) == 'function')
options = val;
else
options.get = val;
options.elementFactory = options.elementFactory ||
function(contentdata, obj, config)
{
var s = '';
for(var i = 0; i < contentdata.length; i++)
{
var o = contentdata[i];
// NEED TO REPLACE THIS
s += '<div class="item"><p>Item ' + o.page + '.' + i + ' <span class="info">' + o.text + '</span></p></div>';
}
return s;
};
$(el).infiniteScroll(options);
return { controlsDescendantBindings: true };
}
}
};
contentdata
是一个对象数组,例如[ { page:1, text:'Item1' }, { page:1, text:'Item2' } ... ]
调用之间的页面大小可能不同;我无法知道该服务将 return;它不是传统的页面,更像是下一个数据块。
所以在元素工厂中,我想以某种方式使用 .scroller
中的标记作为模板绑定 contentdata 数组,类似于 foreach,然后 return 该标记到滚动条插件。
请注意,我可以修改无限滚动源,所以如果不能用字符串完成,returning DOM 元素也可以。
我只是不知道如何 a) 使用内容作为模板,以及 b) return 将绑定结果绑定到插件以便它可以更新其状态。
注意:我最终打算使用的页面目前正在使用 foreach
非平凡对象模型;因此需要使用相同的标记;它需要大量更换。
在这个问题之后,我实际上已经找到了如何使用现有的滚动条来做到这一点:Jquery knockout: Render template in-memory
基本上,您使用 applyBindingsToNode(domelement, bindings)
,这会将 KO 绑定应用于节点集,重要的是不必连接到 DOM。
所以我可以将绑定元素中的标记存储为模板,然后将其清空,然后为元素工厂使用 jQuery 创建一个临时节点集,使用上述函数绑定它,然后 return HTML.
诚然,重构为使用纯 KO 滚动条可能会更好,但这意味着我可以继续使用经过测试和熟悉的插件,代码可能会对人们有所帮助,因为这似乎是一个很常见的问题主题。
这是绑定的新代码(标记如上)。
ko.bindingHandlers.infiniteScroll = {
init:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
if($.fn.infiniteScroll)
{
// Get current value of supplied value
var field = f_valueaccessor();
var val = ko.unwrap(field);
var options = {};
if(typeof(val.get) == 'function')
options = val;
else
options.get = val;
var template = $(el).html();
options.elementFactory = options.elementFactory ||
function(contentdata, obj, config)
{
// Need a root element for foreach to use as a container, as it removes the root element on binding.
var newnodes = $('<div>' + template + '</div>');
ko.applyBindingsToNode(newnodes[0], { foreach: contentdata });
return newnodes.html();
};
$(el)
.empty()
.infiniteScroll(options);
return { controlsDescendantBindings: true };
}
}
};