Note: I didn't make this package! The original can be found here and the author of the fix here.
vue-paginate
的想法非常简单。 你给它一个项目数组; 指定每页有多少项目; 然后让您的项目列表分页!
Setup
npm i @4loop.co/vue-paginate --save
您有两种设置 vue-paginate
的方法:
CommonJS (Webpack/Browserify)
import VuePaginate from 'vue-paginate'
Vue.use(VuePaginate)
var VuePaginate = require('vue-paginate')
Vue.use(VuePaginate)
Include
直接将其包含在
标签中。 在这种情况下,您不需要编写 Vue.use(VuePaginate)
,它会自动为您完成。
Usage
在开始之前,您可能需要查看 jsfiddle 上的一个实例。
vue-paginate
由两个主要组件组成:Paginate
和 PaginateLinks
。 安装插件后,两者都会在全球范围内注册。
要对任何数据列表进行分页,我们必须遵循以下三个小步骤:
- Register the name of the paginated list.
- Use
Paginate
component to paginate and display the paginated list.
- Use
PaginateLinks
component to display the links for the pagination.
现在,让我们在示例中查看它们:
Example
在这个示例中,我们在数据列表中注册了一小部分项目。
new Vue({
el: '#app',
data: {
langs: ['JavaScript', 'PHP', 'HTML', 'CSS', 'Ruby', 'Python', 'Erlang']
}
})
现在,让我们看看如何对该列表进行分页以每页显示两个项目。
第一步是注册我们未来分页列表的名称。 我们通过将它添加到一个名为 paginate
的数组来注册它。
new Vue({
el: '#app',
data: {
langs: ['JavaScript', 'PHP', 'HTML', 'CSS', 'Ruby', 'Python', 'Erlang'],
paginate: ['languages']
}
})
请注意,您可以将其命名为与原始列表相同的名称——为了清楚起见,我在这里将其命名为不同的名称。
第二步是使用 Paginate
组件对列表进行分页。 由于它已由插件全局注册,因此您不必导入它。
该组件至少需要传递两个 props。 已注册分页列表的 name
– 在本例中为 languages
。 以及您要分页的 list
- 在本例中为 langs
。
之后,您开始在该
组件的主体内使用分页列表。 并且,您可以使用 paginated('languages')
方法访问分页列表。
下面是它的实际效果:
<paginate
name="languages"
:list="langs"
:per="2"
>
<li v-for="lang in paginated('languages')">
{{ lang }}
</li>
</paginate>
请注意我们是如何使用 per
属性指定每页的项目数的。 如果我们没有在此处指定它,它将使用默认值,即每页 3
项。
就是这样! 现在您的列表已成功分页。 如果需要,您仍然可以访问原始的 langs
列表。
但是,我们仍然无法浏览这些页面。 这就是 PaginateLinks
组件发挥作用的地方。
该组件需要知道的只是已注册分页列表的名称。 我们使用它的 for
属性传递它。 像这样:
<paginate-links for="languages"></paginate-links>
所以,这是第三步!
Rendering PaginateLinks asynchronously
用户在使用此插件时遇到的一个常见错误是:
[vue-paginate]: can't be used without its companion
出现此错误有两个原因:
- You haven't added your
<paginate>
yet! — Just add it and it will be fixed.
- Or your defined
<paginate>
component is rendered after its companion <paginate-links>
has been rendered (usually happens when using v-if
on <paginate>
or on one of its parents)
这是第二种情况的一些人为示例:
<paginate v-if="shown"
name="items"
:list="items"
>
<li v-for="item in paginated('items')">
{{ item }}
</li>
</paginate>
<paginate-links for="items"></paginate-links>
new Vue({
el: '#app',
data: {
langs: ['JavaScript', 'PHP', 'HTML', 'CSS', 'Ruby', 'Python', 'Erlang'],
paginate: ['languages'],
shown: false
},
mounted () {
setTimeout(() => {
this.shown = true
}, 1000)
}
})
如果您在浏览器中尝试此示例,您将看到本节中描述的错误。 其原因是因为我们的 PaginateLinks
组件无法找到其配套的 Paginate
组件来显示其链接 — 因为它需要整整一秒来呈现自己。
要解决此问题,我们必须告诉我们的 PaginateLinks
等待其配套的 Paginate
组件首先呈现。 我们可以简单地通过在
上使用 :async="true"
来做到这一点。
<paginate-links for="items" :async="true"></paginate-links>
所以底线是这样的:
组件应该始终在
组件之前呈现。
Using it inside a component's slot
Paginate
和 PaginateLinks
组件从使用它们的父组件获取它们的当前状态。您可以在名为 paginate
的对象中找到定义的状态。 例如,如果您的分页名为 languages
,则其状态将在 paginate.languages
中定义。
但是,如果这些组件在 插槽 中使用怎么办? 在这种情况下,它的父组件将是插槽的组件(而不是定义它的组件)。
在这种情况下,我们必须告诉我们的分页组件在哪里可以找到包含其状态的组件。 我们可以使用 container
道具来做到这一点。
尽管 Paginate
和 PaginateLinks
这两个组件使用相同的属性名称,但它们采用不同的值。 Paginate
组件只需要引用具有其状态的父组件。 该值通常是 this
。
然而,PaginateLinks
接受一个具有两个值的对象:state
和 el
。
state
采用分页的当前状态对象。 例如,此值可以是 paginate.languages
。
对于 el
,我们应该传递对包含 Paginate
组件的组件的引用。 在大多数情况下,它将是带有插槽的组件。 例如:$refs.layout
。
Example
注意:这个例子是基于前面的例子。
<div id="app">
<layout ref="layout">
<paginate
name="languages"
:list="langs"
:per="2"
:container="this"
>
<li v-for="lang in paginated('languages')">
{{ lang }}
</li>
</paginate>
<paginate-links
for="languages"
:container="{
state: paginate.languages,
el: $refs.layout
}"
/>
</layout>
</div>
Types of paginate links
vue-paginate
为我们提供了三种不同类型的分页链接:
- Full list of links. This is the default behavior, which displays all available page links from page 1 to N.
- Simple links. It contains only two links: Previous and Next.
- Limited links. It limits the number of displayed links, and provides left and right arrows to help you navigate between them.
Full links
要使用它,您无需执行任何操作; 这是默认行为。
Simple links
为此,我们使用 simple
属性,它接受一个包含 Previous 和 Next 链接名称的对象。 例如:
<paginate-links
for="languages"
:simple="{
prev: 'Back',
next: 'Next'
}"
></paginate-links>
Limited links
要激活此模式,您只需要使用 limit
属性指定限制。 像这样:
<paginate-links
for="languages"
:limit="2"
></paginate-links>
Step Links
在简单链接中,你可以有下一个/上一个链接——我称之为步骤链接——在完整链接和有限链接中。 要添加它们,请在所需的 PaginateLinks
组件上使用 :show-step-links="true"
属性。 例如:
<paginate-links
for="languages"
:show-step-links="true"
></paginate-links>
Customizing step links
步骤链接的默认符号是 «
表示上一个,»
表示下一个。 但是,当然,您可以使用 :step-links
属性将它们更改为您想要的,如下所示:
<paginate-links for="languages"
:show-step-links="true"
:step-links="{
next: 'N',
prev: 'P'
}"
></paginate-links>
Listening to links @change event
当当前页面更改时,PaginateLinks
发出一个名为 < code>change 通知你这件事。 如果需要,它还会传递切换后的页码。
<paginate-links
for="languages"
@change="onLangsPageChange"
></paginate-links>
methods: {
onLangsPageChange (toPage, fromPage) {
// handle here…
}
}
Navigate pages programmatically
Paginate
组件公开了一个方法,允许您手动转到特定页面(而不是通过 PaginateLinks
组件)。 该方法称为 goToPage(pageNumber)
。
要访问此方法,您需要使用 ref
属性访问您的
组件实例。
下面是一个示例:
<paginate ref="paginator"
name="items"
:list="items"
>
<li v-for="item in paginated('items')">
{{ item }}
</li>
</paginate>
<button @click="goToSecondPage">Go to second page</button>
methods: {
goToSecondPage () {
if (this.$refs.paginator) {
this.$refs.paginator.goToPage(2)
}
}
}
Displaying page items count (X-Y of Z
)
分页列表的一个常见需求是显示当前查看项目的项目计数描述。 它通常以这种格式显示 XY of Z
(例如 1-3 of 14
)。
您可以从
组件实例的 pageItemsCount
计算属性中获取它。 为了使用它,您必须使用 ref
属性访问该组件实例。
一个例子:
<paginate ref="paginator"
name="items"
:list="items"
>
<li v-for="item in paginated('items')">
{{ item }}
</li>
</paginate>
<paginate-links for="items"></paginate-links>
<span v-if="$refs.paginator">
Viewing {{$refs.paginator.pageItemsCount}} results
</span>
这里要注意的一件重要事情是 v-if="$refs.paginator"
。 我们需要进行检查以确保我们的
组件实例首先完全呈现。 否则,我们会得到这个错误:
Cannot read property 'pageItemsCount' of undefined"
Paginate container
The default element vue-paginate
uses for the 容器是 UL
。但是,当然,您可以使用 tag
属性将其更改为您想要的任何内容。使用 对其类也是如此>class
prop。
<paginate
name="languages"
:list="langs"
:per="2"
tag="div"
class="paginate-langs"
>
<li v-for="lang in paginated('languages')">
{{ lang }}
</li>
</paginate>
Updating the full list
由于此插件是使用组件系统构建的,因此您可以获得常规 Vue 组件提供的所有灵活性和功能。我在这里专门讨论反应性系统。
所以,当您想要更新原始列表(例如 langs
),只需更新它;一切都将无缝运行!
Filtering the paginated list
插件没有什么特别的支持列表过滤。过滤传递给 component via list
prop.
所以,如果我们要过滤列表(或任何其他操作),我们会得到类似于这样的东西:
// Assume we have a text input bound to `searchLangs` data via v-model for example.
computed: {
fLangs () {
const re = new RegExp(this.searchLangs, 'i')
return this.langs.filter(lang => lang.match(re))
}
}
然后只需传递那个 fLangs 到 list
属性而不是原来的 langs
。
Hide single page
默认情况下,分页链接将始终显示,即使只有一页。 但有时你想在只有一个页面时隐藏它——尤其是在过滤项目之后。 该插件允许您通过使用 :hide-single-page="true"
道具来做到这一点。
<paginate-links for="items"
:hide-single-page="true"
></paginate-links>
Links customization
在 vue-paginate
中,您可以自定义分页链接的每一部分。
但首先,让我们看看用于所有链接类型的 html 结构:
<ul>
<li><a>1</a></li>
<li><a>2</a></li>
<!-- … -->
</ul>
现在,让我们看看我们经常需要使用的 CSS 选择器:
All links containers:
ul.paginate-links
Specific links container:
ul.paginate-links.languages< /code>
languages
这里是分页列表的名称。
Current page:
这仅适用于完整的 & 有限的链接。
<代码>ul.paginate-链接> li.active > a
Previous & Next Links:
显然,这只是针对简单的链接。
上一个 -> <代码>ul.paginate-链接> li.prev > a
下一步 –> <代码>ul.paginate-链接> li.next >
Disabled Next/Previous Links:
ul.paginate-links > li.disabled > a
Limited Links:
数字链接 –> <代码>ul.paginate-链接> li.number> a
向左箭头 –> <代码>ul.paginate-链接> li.left-arrow > a
向右箭头 –> <代码>ul.paginate-链接> li.right-arrow > a
省略号 –> <代码>ul.paginate-链接> li.ellipses > a
Adding additional classes
在某些情况下,尤其是当您使用 CSS 框架时,您需要向链接元素添加额外的类。 您可以简单地通过在 PaginateLinks
组件上使用 classes
道具来做到这一点。 该道具将包含元素选择器的对象作为键,将要添加的类作为值。
下面是一个示例:
<paginate-links
for="languages"
:simple="{
prev: 'Back',
next: 'Next'
}"
:classes="{
'ul': 'simple-links-container',
'.next > a': 'next-link',
'.prev > a': ['prev-link', 'another-class'] // multiple classes
}"
></paginate-links>
请注意,此功能适用于所有链接类型——完整链接、简单链接和有限链接。
License
MIT
版权所有 (c) 2016–2017 Taha Shashtari
Note: I didn't make this package! The original can be found here and the author of the fix here.
The idea of vue-paginate
is pretty simple. You give it an array of items; specify how many items per page; then get your list of items paginated!
Setup
npm i @4loop.co/vue-paginate --save
You have two ways to setup vue-paginate
:
CommonJS (Webpack/Browserify)
import VuePaginate from 'vue-paginate'
Vue.use(VuePaginate)
var VuePaginate = require('vue-paginate')
Vue.use(VuePaginate)
Include
Include it directly with a <script>
tag. In this case, you don't need to write Vue.use(VuePaginate)
, this will be done automatically for you.
Usage
Before you start, you may want to check a live example on jsfiddle.
vue-paginate
consists of two main components: Paginate
and PaginateLinks
. And both get registered globally once the plugin is installed.
To paginate any list of data, we have to follow these three small steps:
- Register the name of the paginated list.
- Use
Paginate
component to paginate and display the paginated list.
- Use
PaginateLinks
component to display the links for the pagination.
Now, let’s see them in an example:
Example
In this example, we have a small list of items registered in our data list.
new Vue({
el: '#app',
data: {
langs: ['JavaScript', 'PHP', 'HTML', 'CSS', 'Ruby', 'Python', 'Erlang']
}
})
Now, let’s see how we can paginate this list to display two items per page.
First step is to register the name of our future paginated list. We register it by adding it to an array called paginate
.
new Vue({
el: '#app',
data: {
langs: ['JavaScript', 'PHP', 'HTML', 'CSS', 'Ruby', 'Python', 'Erlang'],
paginate: ['languages']
}
})
Note that you can name it the same as the original list – I named it differently here just for the sake of clarity.
Second step is to use the Paginate
component to paginate the list. Since it was globally registered by the plugin, you don’t have to import it.
This component requires at least two props to be passed. The name
of the registered paginated list – languages
in this case. And the list
that you want to paginate – langs
in this case.
After that, you start using the paginated list inside the body of that <paginate>
component. And, you get access to the paginated list using the method paginated('languages')
.
Here’s how it looks in action:
<paginate
name="languages"
:list="langs"
:per="2"
>
<li v-for="lang in paginated('languages')">
{{ lang }}
</li>
</paginate>
Note how we specified the number of items per page using the per
prop. If we didn’t specify it here, it would use the default value instead, which is 3
items per page.
That’s it! Now your list has been paginated successfully. And you still have access to the original langs
list if you need it.
However, we still don’t have a way to navigate through those pages. Here’s where PaginateLinks
component comes into play.
All that component needs to know is the name of the registered paginated list. We pass that using its for
prop. Like this:
<paginate-links for="languages"></paginate-links>
So, that was the third step!
Rendering PaginateLinks asynchronously
A common error users get when using this plugin is this:
[vue-paginate]: can't be used without its companion
This error occurs for two reasons:
- You haven't added your
<paginate>
yet! — Just add it and it will be fixed.
- Or your defined
<paginate>
component is rendered after its companion <paginate-links>
has been rendered (usually happens when using v-if
on <paginate>
or on one of its parents)
Here's some contrived example of the second case:
<paginate v-if="shown"
name="items"
:list="items"
>
<li v-for="item in paginated('items')">
{{ item }}
</li>
</paginate>
<paginate-links for="items"></paginate-links>
new Vue({
el: '#app',
data: {
langs: ['JavaScript', 'PHP', 'HTML', 'CSS', 'Ruby', 'Python', 'Erlang'],
paginate: ['languages'],
shown: false
},
mounted () {
setTimeout(() => {
this.shown = true
}, 1000)
}
})
If you try this example in the browser, you'll see the error described in this section. And the reason for that is because our PaginateLinks
component can't find its companion Paginate
component to show the links for — since it takes a complete second to render itself.
To fix this issue we have to tell our PaginateLinks
to wait for its companion Paginate
component to be rendered first. And we can do that simply by using :async="true"
on <paginate-links>
.
<paginate-links for="items" :async="true"></paginate-links>
So the bottom line is this: <paginate>
component should always be rendered before <paginate-links>
component.
Using it inside a component's slot
Paginate
and PaginateLinks
components get their current state from the parent component they're used in. You can find that state defined inside an object called paginate
. For example, if your pagination is named languages
, its state will be defined inside paginate.languages
.
But what if those components are used inside a slot? In this case, its parent component will be the slot's component (not the component it's defined in).
In this case we have to tell our pagination components where they can find the component that contains their state. We can do so using the container
prop.
Although both components, Paginate
and PaginateLinks
, use the same prop name, they take different values. Paginate
component just needs the reference to the parent component that has its state. That value is usually this
.
PaginateLinks
, however, takes an object with two values: state
and el
.
state
takes the current state object of the pagination. This value can be, for example, paginate.languages
.
For el
we should pass a reference to the component that contains Paginate
component. In most cases it will be the component with the slot. For example: $refs.layout
.
Example
Note: this example is based on the previous example.
<div id="app">
<layout ref="layout">
<paginate
name="languages"
:list="langs"
:per="2"
:container="this"
>
<li v-for="lang in paginated('languages')">
{{ lang }}
</li>
</paginate>
<paginate-links
for="languages"
:container="{
state: paginate.languages,
el: $refs.layout
}"
/>
</layout>
</div>
Types of paginate links
vue-paginate
provides us with three different types of pagination links:
- Full list of links. This is the default behavior, which displays all available page links from page 1 to N.
- Simple links. It contains only two links: Previous and Next.
- Limited links. It limits the number of displayed links, and provides left and right arrows to help you navigate between them.
Full links
To use this you don’t have to do anything; this is the default behavior.
Simple links
For this, we use the simple
prop, which accepts an object that contains the names of the Previous and Next links. For example:
<paginate-links
for="languages"
:simple="{
prev: 'Back',
next: 'Next'
}"
></paginate-links>
Limited links
To activate this mode, you just need to specify the limit using the limit
prop. Like this:
<paginate-links
for="languages"
:limit="2"
></paginate-links>
Step Links
As in simple links, you can have next/previous links — which I call step links — in full links and limited links. To add them, use :show-step-links="true"
prop on the PaginateLinks
component you want. For example:
<paginate-links
for="languages"
:show-step-links="true"
></paginate-links>
Customizing step links
The default symbols for the step links are «
for previous and »
for next. But, of course, you can change them to what you want using the :step-links
prop, like this:
<paginate-links for="languages"
:show-step-links="true"
:step-links="{
next: 'N',
prev: 'P'
}"
></paginate-links>
Listening to links @change event
When the current page changes, PaginateLinks
emits an event called change
to inform you about that. It also passes the switched page numbers with it, if you need them.
<paginate-links
for="languages"
@change="onLangsPageChange"
></paginate-links>
methods: {
onLangsPageChange (toPage, fromPage) {
// handle here…
}
}
Navigate pages programmatically
Paginate
component exposes a method that allows you to go to a specific page manually (not through PaginateLinks
component). That method is called goToPage(pageNumber)
.
To access this method, you need to get an access to your <paginate>
component instance using ref
property.
Here's an example:
<paginate ref="paginator"
name="items"
:list="items"
>
<li v-for="item in paginated('items')">
{{ item }}
</li>
</paginate>
<button @click="goToSecondPage">Go to second page</button>
methods: {
goToSecondPage () {
if (this.$refs.paginator) {
this.$refs.paginator.goToPage(2)
}
}
}
Displaying page items count (X-Y of Z
)
A common need for paginated lists is to display the items count description of the currently viewed items. It's usually displayed in this format X-Y of Z
(e.g. 1-3 of 14
).
You can get that from your <paginate>
component instance's pageItemsCount
computed property. And in order to use that, you have to get an access to that component instance using ref
property.
An example:
<paginate ref="paginator"
name="items"
:list="items"
>
<li v-for="item in paginated('items')">
{{ item }}
</li>
</paginate>
<paginate-links for="items"></paginate-links>
<span v-if="$refs.paginator">
Viewing {{$refs.paginator.pageItemsCount}} results
</span>
An important thing to note here is v-if="$refs.paginator"
. We needed to do that check to make sure our <paginate>
component instance is completely rendered first. Otherwise, we'll get this error:
Cannot read property 'pageItemsCount' of undefined"
Paginate container
The default element vue-paginate
uses for the <paginate>
container is UL
. But, of course, you can change it to whatever you want using the tag
prop. And the same is true for its class using the class
prop.
<paginate
name="languages"
:list="langs"
:per="2"
tag="div"
class="paginate-langs"
>
<li v-for="lang in paginated('languages')">
{{ lang }}
</li>
</paginate>
Updating the full list
Since this plugin is built using the components system, you get all the flexibility and power that regular Vue components provide. I’m talking here specifically about the reactivity system.
So, when you want to update the original list (e.g. langs
), just update it; everything will work seamlessly!
Filtering the paginated list
There’s nothing special the plugin does to support list filtering. It’s your responsibility to filter the list you pass to <paginate>
component via list
prop.
So, if we were to filter the list (or any other operation), we would have something similar to this:
// Assume we have a text input bound to `searchLangs` data via v-model for example.
computed: {
fLangs () {
const re = new RegExp(this.searchLangs, 'i')
return this.langs.filter(lang => lang.match(re))
}
}
Then just pass that fLangs
to the list
prop instead of the original langs
.
Hide single page
By default, paginated links will always be displayed even if there's only one page. But sometimes you want to hide it when there's a single page — especially after filtering the items. The plugin allows you to do so by using the :hide-single-page="true"
prop.
<paginate-links for="items"
:hide-single-page="true"
></paginate-links>
Links customization
In vue-paginate
, you can customize every bit of your pagination links.
But first, let’s see the html structure used for all link types:
<ul>
<li><a>1</a></li>
<li><a>2</a></li>
<!-- … -->
</ul>
Now, let’s see what CSS selectors we often need to use:
All links containers:
ul.paginate-links
Specific links container:
ul.paginate-links.languages
languages
here is the name of your paginated list.
Current page:
This only works for full & limited links.
ul.paginate-links > li.active > a
Previous & Next Links:
Obviously, this is only for simple links.
Previous –> ul.paginate-links > li.prev > a
Next –> ul.paginate-links > li.next > a
Disabled Next/Previous Links:
ul.paginate-links > li.disabled > a
Limited Links:
Number links –> ul.paginate-links > li.number > a
Left arrow –> ul.paginate-links > li.left-arrow > a
Right arrow –> ul.paginate-links > li.right-arrow > a
Ellipses –> ul.paginate-links > li.ellipses > a
Adding additional classes
In some cases, especially when you're using a CSS framework, you'll need to add additional classes to your links elements. You can do so simply by using the classes
prop on your PaginateLinks
component. This prop takes an object that contains the element's selector as the key, and the class you want to add as the value.
Here's an example:
<paginate-links
for="languages"
:simple="{
prev: 'Back',
next: 'Next'
}"
:classes="{
'ul': 'simple-links-container',
'.next > a': 'next-link',
'.prev > a': ['prev-link', 'another-class'] // multiple classes
}"
></paginate-links>
Note that this feature works on all link types – full links, simple links, and limited links.
License
MIT
Copyright (c) 2016–2017 Taha Shashtari