PagerJS可以获取URL参数并将它们绑定到模型。例如,在这个来自PagerJS网站(see link)的示例中,当您单击该链接时,它将导航到#/user?first=Philip&last=Fry
,并且将出现数据绑定子页面,显示“Philip Fry” :
<a class="btn" data-bind="page-href: {path: 'user', params: {first: 'Philip', last: 'Fry'}}">Send parameter to page</a>
<div data-bind="page: {id: 'user', params: ['first','last']}" class="well-small">
<div>
<span>First name:</span>
<span data-bind="text: first"></span>
</div>
<div>
<span>Last name:</span>
<span data-bind="text: last"></span>
</div>
</div>
这是一种单向绑定:如果observable发生更改,由于页面上的用户操作,URL将不会更新。
使用PagerJS时,建议的方法是使URL参数与observable保持同步?
我想在URL参数中存储用户动态创建的搜索条件(通过选择一组UI控件生成),这样他/她就可以与其他人共享URL或将其加入书签,所有这些都无需重新加载页面,当然。
答案 0 :(得分:5)
免责声明:我对pager.js一无所知,但我希望我的一般淘汰赛经验仍然有用。
查看示例,page
绑定似乎使用url中的初始值创建了observable。我的第一直觉是扩展此绑定,并确保订阅每个值都会更新URL。
让我们命名这个绑定twoway-page
:
ko.bindingHandlers["twoway-page"] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// Call pager.js' page binding
ko.bindingHandlers.page.init(element, valueAccessor, allBindings, viewModel, bindingContext);
// ...
}
}
并在示例的绑定中调用它:
<div data-bind="twoway-page: {
id: 'start',
params: ['first','last']
}">
调用page.init
后,页面绑定扩展了viewmodel,将params
数组中定义的observable添加到viewModel
对象。这意味着我们可以订阅这些可观察量的变化。
下一个挑战是计算正确的哈希值。我查看了page-href
绑定如何计算其href
属性。事实证明它在具有pager.page.path()
和path
属性的对象上使用params
。 E.g:
var hash = pager.page.path({
path: "user",
params: {
"first": "John",
"last": "Doe"
}
});
我试图在计算的observable中构造一个类似的对象。
// ...
var options = valueAccessor();
var pathObj = ko.computed(function() {
var result = {
path: options.id,
params: {}
};
options.params.forEach(function(param) {
result.params[param] = viewModel[param]();
});
return result;
}).extend({ rateLimit: { timeout: 200, method: "notifyWhenChangesStop" } });
我找不到&#34;清洁&#34;通过pager.js方法更新哈希的方法,但我注意到内部,pagerjs使用location.hash = "newhash"
来设置一个值(尽管似乎还有一个history / html5替代方法......)。无论如何,我们可以订阅我们的observable来更新哈希:
// ...
pathObj.subscribe(function(newValue) {
location.hash = pager.page.path(newValue);
});
现在,我们将使用text
绑定代替示例中的textInput
绑定,以便我们更新值:
<div>
<span>First name:</span>
<input type="text" data-bind="textInput: first">
</div>
所以,结束:我最好的猜测是
rateLimit
扩展名来防止更新过载使用位置哈希做一些东西有点难以在小提琴中显示,所以我记录了我的概念证明的gif:
完整的自定义绑定代码是:
ko.bindingHandlers["twoway-page"] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.bindingHandlers.page.init(element, valueAccessor, allBindings, viewModel, bindingContext)
var options = valueAccessor();
var pathObj = ko.computed(function() {
var result = {
path: options.id,
params: {}
};
options.params.forEach(function(param) {
result.params[param] = viewModel[param]();
});
return result;
}).extend({ rateLimit: { timeout: 200, method: "notifyWhenChangesStop" } });
pathObj.subscribe(function(newValue) {
location.hash = pager.page.path(newValue);
})
return { controlsDescendantBindings: true }
}
};
答案 1 :(得分:2)
我无法添加评论,所以我必须添加一个新答案。
user3297291
给出了非常好的答案,它对我帮助很大。
但是,现实世界中出现了一些问题,例如:
深度导航:页面,子页面,子页面等
options.id
是不够的,我们需要完整的路径
page/subpage/subsubpage
(没有#!/
)
在页面之间共享一些URL参数时,只要参数更改,每个页面都会触发导航,最后一个将显示。我在某些页面(productID等)之间共享相同的ID参数。
对于问题1,计算完整路径:
...var options = valueAccessor();
var parent = pager.getParentPage(bindingContext);
var fullroute = parent.getFullRoute()();
if(fullroute.length == 0)
var path = fullroute.join('/')+options.id;
else
var path = fullroute.join('/')+'/'+options.id;
result
对象变为:
var result = {
path: path,
params: {}
};
对于问题2,我们必须告诉他们,只有当活动页面是他们自己的时候,他们才能触发导航。
在subscribe方法中,我们计算activePage路径并比较它们:
pathObj.subscribe(function(newValue) {
//calculate activePath
var activeParent = pager.activePage$().parentPage.getFullRoute()();
var activeId = pager.activePage$().getCurrentId();
if(activeParent.length == 0)
var activePath = activeParent .join('/')+activeId;
else
var activePath = activeParent .join('/')+'/'+activeId;
if( path == activePath ){
location.hash = pager.page.path(newValue);
}
})
另外,在循环抛出params时要小心,如果你提供了默认值,它可以是一个数组或一个对象:
<div data-bind="page: {id: 'search', params: ['product','price']}" class="well">
需要:
options.params.forEach(function(param) {...
Vs的
<div data-bind="page: {id: 'search', params: {'product': null,'price': 0}}" class="well">
需要类似的东西:
Object.keys(options.params).forEach(function(key,index) {
result.params[key] = viewModel[key]();
}
再次感谢user3297291的回答,它确实有所不同。