如何使用 Knockout 处理分页
[英] How to handle pagination with Knockout
本文介绍了如何使用 Knockout 处理分页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个设置为绑定到 observeableArray
的 div,但我只想在任何给定时间显示该 observeableArray
中最多 50 个项目.我想通过使用上一个和下一个按钮以及页面上的索引进行分页来处理这个问题,以允许用户循环浏览集合中的项目页面.
我知道我可能可以使用 computedObservable
和自定义数据绑定,但我不知道该怎么做(我仍然是 Knockout 新手).
谁能指出我正确的方向?
这是我的代码(JS 在 TypeScript 中):
<div class="row-fluid"><div class="span12"><%=如果参数[:q]呈现'active_search.html.erb'别的呈现'passive_search.html.erb'结尾%><%= form_tag("/search", method: "get", :class => "form-search form-inline") do %><%= label_tag(:q, "搜索:") %><%= text_field_tag(:q, nil, class:"input-medium search-query") %><%= submit_tag("搜索", :class=>"btn") %><%结束%><div class="media" data-bind="foreach: tweetsArray"><%= image_tag('twitter-icon.svg', :class=>"tweet_img", :style=>"display:inline;") %><div class="media-body" style="display:inline;"><h4 class="media-heading" data-bind="text: user.screen_name" style="display:inline;"></h4><span data-bind="text:text" style="display:inline;"></span><br/><span data-bind="text:'Created at '+created_at"></span><br/>
<div class="分页以分页为中心"><ul><li><a href="#">上一页</a><li><a href="#">1</a><li><a href="#">下一步</a>
<脚本>var viewModel = new twitterResearch.TweetViewModel();ko.applyBindings(viewModel);//TODO: 给自己的注释,使用自定义绑定进行分页以及计算出的 observable 来确定您在列表中的位置//document.onReady 回调函数$(函数(){$.getJSON('twitter', {}, function(data) {viewModel.pushTweet(data);控制台日志(数据.用户);});});声明 var $: any;声明 var ko: 任何;模块推特研究{类推文{文本:字符串;created_at: 字符串;坐标:字符串;用户:字符串;实体:字符串;身份证号码;id_str:字符串;构造函数(_text: string, _created_at: string, _coordinates: any, _user: any,_entities:任何,_id_str:字符串,_id:数字){this.text = _text;this.created_at = _created_at;this.coordinates = _coordinates;this.user = _user;this.entities = _entities;this.id_str = _id_str;this.id = _id;}}导出类 TweetViewModel{tweetsArray: 任何;构造函数(){this.tweetsArray = ko.observableArray([]);}//tweet 将是我们返回的 JSON 推文//来自服务器推特(推特){var _tweet = new Tweet(tweet.text, tweet.created_at, tweet.coordinates,tweet.user、tweet.entities、tweet.id_str、tweet.id);this.tweetsArray.push(_tweet);this.tweetsArray.valueHasMutated();}}}
解决方案
使用 Knockout 进行分页非常简单.我个人会通过这种方式实现它:
- 有一个包含所有元素的 observableArray
- 有一个包含当前页面的 observable(初始化为 0)
- 有一个变量来声明每页的元素数量
- 计算返回页数,这要归功于每页的元素数和元素总数.
- 最后,添加一个对包含所有元素的数组进行切片的计算.
鉴于此,您现在可以添加一个增加(下一个)或减少(上一个)当前页面的函数.
这是一个简单的例子:
var Model = function() {var self = this;this.all = ko.observableArray([]);this.pageNumber = ko.observable(0);this.nbPerPage = 25;this.totalPages = ko.computed(function() {var div = Math.floor(self.all().length/self.nbPerPage);div += self.all().length % self.nbPerPage >0 ?1:0;返回 div - 1;});this.paginated = ko.computed(function() {var first = self.pageNumber() * self.nbPerPage;return self.all.slice(first, first + self.nbPerPage);});this.hasPrevious = ko.computed(function() {返回 self.pageNumber() !== 0;});this.hasNext = ko.computed(function() {返回 self.pageNumber() !== self.totalPages();});this.next = 函数(){if(self.pageNumber() < self.totalPages()) {self.pageNumber(self.pageNumber() + 1);}}this.previous = 函数(){if(self.pageNumber() != 0) {self.pageNumber(self.pageNumber() - 1);}}}
您会在这里找到一个简单而完整的示例:http://jsfiddle.net/LAbCv/(可能有点问题,但想法是存在的).
I have a div that is setup to bind to a observeableArray
,but I only want to show at most 50 items from that observeableArray
at any given time. I want to handle this with pagination with a previous and next button along with indices on the page to allow users to cycle through pages of items from the collection.
I know I could probably do this with a computedObservable
and a custom data binding but I'm not sure how to do it (I'm still a Knockout neophyte).
Can anyone point me in the right direction?
Here is my code (the JS is in TypeScript):
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<%=
if params[:q]
render 'active_search.html.erb'
else
render 'passive_search.html.erb'
end
%>
<%= form_tag("/search", method: "get", :class => "form-search form-inline") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q, nil, class:"input-medium search-query") %>
<%= submit_tag("Search", :class=>"btn") %>
<% end %>
<div class="media" data-bind="foreach: tweetsArray">
<%= image_tag('twitter-icon.svg', :class=>"tweet_img", :style=>"display:inline;") %>
<div class="media-body" style="display:inline;">
<h4 class="media-heading" data-bind="text: user.screen_name" style="display:inline;"></h4>
<span data-bind="text:text" style="display:inline;"></span> <br />
<span data-bind="text:'Created at '+created_at"></span> <br />
</div>
</div>
<div class="pagination pagination-centered">
<ul>
<li>
<a href="#">Prev</a>
</li>
<li>
<a href="#">1</a>
</li>
<li>
<a href="#">Next</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<script>
var viewModel = new twitterResearch.TweetViewModel();
ko.applyBindings(viewModel);
//TODO: notes to self, use custom binding for pagination along with a computed observable to determine where at in the list you are
//document.onReady callback function
$(function() {
$.getJSON('twitter', {}, function(data) {
viewModel.pushTweet(data);
console.log(data.user);
});
});
</script>
declare var $: any;
declare var ko: any;
module twitterResearch {
class Tweet {
text: string;
created_at: string;
coordinates: string;
user: string;
entities: string;
id: number;
id_str: string;
constructor(_text: string, _created_at: string, _coordinates: any, _user: any,
_entities: any, _id_str: string, _id: number){
this.text = _text;
this.created_at = _created_at;
this.coordinates = _coordinates;
this.user = _user;
this.entities = _entities;
this.id_str = _id_str;
this.id = _id;
}
}
export class TweetViewModel{
tweetsArray: any;
constructor()
{
this.tweetsArray = ko.observableArray([]);
}
//tweet is going to be the JSON tweet we return
//from the server
pushTweet(tweet)
{
var _tweet = new Tweet(tweet.text, tweet.created_at, tweet.coordinates,
tweet.user, tweet.entities, tweet.id_str, tweet.id);
this.tweetsArray.push(_tweet);
this.tweetsArray.valueHasMutated();
}
}
}
解决方案
Pagination is quite simple with Knockout. I would personally achieve it this way:
- Have an observableArray containing all your elements
- Have an observable containing the current page (initialized to 0)
- Have a variable declaring the number of elements per page
- Have a computed that returns the number of pages, calculated thanks to the number of elements per page and the total number of elements.
- Finally, add a computed that slices the array containing all the elements.
Given that, you can now add a function that increments (next) or decrements (previous) the current page.
Here is a quick example:
var Model = function() {
var self = this;
this.all = ko.observableArray([]);
this.pageNumber = ko.observable(0);
this.nbPerPage = 25;
this.totalPages = ko.computed(function() {
var div = Math.floor(self.all().length / self.nbPerPage);
div += self.all().length % self.nbPerPage > 0 ? 1 : 0;
return div - 1;
});
this.paginated = ko.computed(function() {
var first = self.pageNumber() * self.nbPerPage;
return self.all.slice(first, first + self.nbPerPage);
});
this.hasPrevious = ko.computed(function() {
return self.pageNumber() !== 0;
});
this.hasNext = ko.computed(function() {
return self.pageNumber() !== self.totalPages();
});
this.next = function() {
if(self.pageNumber() < self.totalPages()) {
self.pageNumber(self.pageNumber() + 1);
}
}
this.previous = function() {
if(self.pageNumber() != 0) {
self.pageNumber(self.pageNumber() - 1);
}
}
}
You'll find a simple and complete example here: http://jsfiddle.net/LAbCv/ (might be a bit buggy, but the idea is there).
这篇关于如何使用 Knockout 处理分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!