vue如何自定义翻页组件

发布时间:2022-10-22 14:57:24 作者:iii
来源:亿速云 阅读:154

Vue如何自定义翻页组件

在现代Web开发中,分页功能是几乎每个数据密集型应用都需要的功能。无论是展示用户列表、商品列表还是其他类型的数据,分页都是必不可少的。Vue.js流行的前端框架,提供了强大的工具和灵活性,使得自定义翻页组件变得相对简单。本文将详细介绍如何在Vue中自定义一个翻页组件,涵盖从基础概念到实际实现的各个方面。

1. 理解分页的基本概念

在开始编写代码之前,首先需要理解分页的基本概念。分页通常包括以下几个关键部分:

2. 设计翻页组件的结构

在设计翻页组件时,我们需要考虑组件的结构、样式和交互。一个典型的翻页组件可能包括以下元素:

3. 创建Vue组件

接下来,我们将创建一个Vue组件来实现上述功能。我们将使用Vue 3的Composition API来编写这个组件。

3.1 创建基础组件

首先,创建一个名为Pagination.vue的文件,并定义组件的基本结构。

<template>
  <div class="pagination">
    <button @click="prevPage" :disabled="currentPage === 1">上一页</button>
    <span v-for="page in pages" :key="page" @click="goToPage(page)" :class="{ active: page === currentPage }">
      {{ page }}
    </span>
    <button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  props: {
    totalItems: {
      type: Number,
      required: true,
    },
    itemsPerPage: {
      type: Number,
      required: true,
    },
  },
  setup(props) {
    const currentPage = ref(1);

    const totalPages = computed(() => Math.ceil(props.totalItems / props.itemsPerPage));

    const pages = computed(() => {
      const pagesArray = [];
      for (let i = 1; i <= totalPages.value; i++) {
        pagesArray.push(i);
      }
      return pagesArray;
    });

    const prevPage = () => {
      if (currentPage.value > 1) {
        currentPage.value--;
      }
    };

    const nextPage = () => {
      if (currentPage.value < totalPages.value) {
        currentPage.value++;
      }
    };

    const goToPage = (page) => {
      if (page >= 1 && page <= totalPages.value) {
        currentPage.value = page;
      }
    };

    return {
      currentPage,
      totalPages,
      pages,
      prevPage,
      nextPage,
      goToPage,
    };
  },
};
</script>

<style scoped>
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20px;
}

button {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span.active {
  font-weight: bold;
  color: blue;
}
</style>

3.2 解释代码

3.3 使用组件

在父组件中使用Pagination组件时,需要传递totalItemsitemsPerPage两个props。

<template>
  <div>
    <!-- 数据展示部分 -->
    <ul>
      <li v-for="item in paginatedItems" :key="item.id">{{ item.name }}</li>
    </ul>

    <!-- 分页组件 -->
    <Pagination :totalItems="items.length" :itemsPerPage="itemsPerPage" />
  </div>
</template>

<script>
import { ref, computed } from 'vue';
import Pagination from './Pagination.vue';

export default {
  components: {
    Pagination,
  },
  setup() {
    const items = ref([
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      // 更多数据...
    ]);

    const itemsPerPage = ref(5);

    const paginatedItems = computed(() => {
      const start = (currentPage.value - 1) * itemsPerPage.value;
      const end = start + itemsPerPage.value;
      return items.value.slice(start, end);
    });

    return {
      items,
      itemsPerPage,
      paginatedItems,
    };
  },
};
</script>

4. 添加更多功能

4.1 跳转输入框

为了允许用户直接跳转到指定页码,我们可以添加一个输入框。

<template>
  <div class="pagination">
    <button @click="prevPage" :disabled="currentPage === 1">上一页</button>
    <span v-for="page in pages" :key="page" @click="goToPage(page)" :class="{ active: page === currentPage }">
      {{ page }}
    </span>
    <button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
    <input type="number" v-model="inputPage" @keyup.enter="goToPage(inputPage)" />
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  props: {
    totalItems: {
      type: Number,
      required: true,
    },
    itemsPerPage: {
      type: Number,
      required: true,
    },
  },
  setup(props) {
    const currentPage = ref(1);
    const inputPage = ref('');

    const totalPages = computed(() => Math.ceil(props.totalItems / props.itemsPerPage));

    const pages = computed(() => {
      const pagesArray = [];
      for (let i = 1; i <= totalPages.value; i++) {
        pagesArray.push(i);
      }
      return pagesArray;
    });

    const prevPage = () => {
      if (currentPage.value > 1) {
        currentPage.value--;
      }
    };

    const nextPage = () => {
      if (currentPage.value < totalPages.value) {
        currentPage.value++;
      }
    };

    const goToPage = (page) => {
      if (page >= 1 && page <= totalPages.value) {
        currentPage.value = page;
      }
    };

    return {
      currentPage,
      inputPage,
      totalPages,
      pages,
      prevPage,
      nextPage,
      goToPage,
    };
  },
};
</script>

<style scoped>
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20px;
}

button {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span.active {
  font-weight: bold;
  color: blue;
}

input {
  margin-left: 10px;
  width: 50px;
}
</style>

4.2 限制显示的页码数量

当总页数较多时,显示所有页码可能会导致页面过长。我们可以限制显示的页码数量,并使用省略号表示省略的页码。

<template>
  <div class="pagination">
    <button @click="prevPage" :disabled="currentPage === 1">上一页</button>
    <span v-if="currentPage > 3" @click="goToPage(1)">1</span>
    <span v-if="currentPage > 4">...</span>
    <span v-for="page in visiblePages" :key="page" @click="goToPage(page)" :class="{ active: page === currentPage }">
      {{ page }}
    </span>
    <span v-if="currentPage < totalPages - 3">...</span>
    <span v-if="currentPage < totalPages - 2" @click="goToPage(totalPages)">{{ totalPages }}</span>
    <button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
    <input type="number" v-model="inputPage" @keyup.enter="goToPage(inputPage)" />
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  props: {
    totalItems: {
      type: Number,
      required: true,
    },
    itemsPerPage: {
      type: Number,
      required: true,
    },
  },
  setup(props) {
    const currentPage = ref(1);
    const inputPage = ref('');

    const totalPages = computed(() => Math.ceil(props.totalItems / props.itemsPerPage));

    const visiblePages = computed(() => {
      const pagesArray = [];
      let start = Math.max(1, currentPage.value - 2);
      let end = Math.min(totalPages.value, currentPage.value + 2);

      for (let i = start; i <= end; i++) {
        pagesArray.push(i);
      }
      return pagesArray;
    });

    const prevPage = () => {
      if (currentPage.value > 1) {
        currentPage.value--;
      }
    };

    const nextPage = () => {
      if (currentPage.value < totalPages.value) {
        currentPage.value++;
      }
    };

    const goToPage = (page) => {
      if (page >= 1 && page <= totalPages.value) {
        currentPage.value = page;
      }
    };

    return {
      currentPage,
      inputPage,
      totalPages,
      visiblePages,
      prevPage,
      nextPage,
      goToPage,
    };
  },
};
</script>

<style scoped>
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20px;
}

button {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span.active {
  font-weight: bold;
  color: blue;
}

input {
  margin-left: 10px;
  width: 50px;
}
</style>

4.3 添加事件监听

为了让父组件能够响应页码的变化,我们可以通过emit事件来通知父组件当前页码的变化。

<template>
  <div class="pagination">
    <button @click="prevPage" :disabled="currentPage === 1">上一页</button>
    <span v-if="currentPage > 3" @click="goToPage(1)">1</span>
    <span v-if="currentPage > 4">...</span>
    <span v-for="page in visiblePages" :key="page" @click="goToPage(page)" :class="{ active: page === currentPage }">
      {{ page }}
    </span>
    <span v-if="currentPage < totalPages - 3">...</span>
    <span v-if="currentPage < totalPages - 2" @click="goToPage(totalPages)">{{ totalPages }}</span>
    <button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
    <input type="number" v-model="inputPage" @keyup.enter="goToPage(inputPage)" />
  </div>
</template>

<script>
import { ref, computed, watch } from 'vue';

export default {
  props: {
    totalItems: {
      type: Number,
      required: true,
    },
    itemsPerPage: {
      type: Number,
      required: true,
    },
  },
  emits: ['page-change'],
  setup(props, { emit }) {
    const currentPage = ref(1);
    const inputPage = ref('');

    const totalPages = computed(() => Math.ceil(props.totalItems / props.itemsPerPage));

    const visiblePages = computed(() => {
      const pagesArray = [];
      let start = Math.max(1, currentPage.value - 2);
      let end = Math.min(totalPages.value, currentPage.value + 2);

      for (let i = start; i <= end; i++) {
        pagesArray.push(i);
      }
      return pagesArray;
    });

    const prevPage = () => {
      if (currentPage.value > 1) {
        currentPage.value--;
      }
    };

    const nextPage = () => {
      if (currentPage.value < totalPages.value) {
        currentPage.value++;
      }
    };

    const goToPage = (page) => {
      if (page >= 1 && page <= totalPages.value) {
        currentPage.value = page;
      }
    };

    watch(currentPage, (newPage) => {
      emit('page-change', newPage);
    });

    return {
      currentPage,
      inputPage,
      totalPages,
      visiblePages,
      prevPage,
      nextPage,
      goToPage,
    };
  },
};
</script>

<style scoped>
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20px;
}

button {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span {
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
}

span.active {
  font-weight: bold;
  color: blue;
}

input {
  margin-left: 10px;
  width: 50px;
}
</style>

在父组件中,可以通过监听page-change事件来响应页码的变化。

<template>
  <div>
    <!-- 数据展示部分 -->
    <ul>
      <li v-for="item in paginatedItems" :key="item.id">{{ item.name }}</li>
    </ul>

    <!-- 分页组件 -->
    <Pagination :totalItems="items.length" :itemsPerPage="itemsPerPage" @page-change="handlePageChange" />
  </div>
</template>

<script>
import { ref, computed } from 'vue';
import Pagination from './Pagination.vue';

export default {
  components: {
    Pagination,
  },
  setup() {
    const items = ref([
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      // 更多数据...
    ]);

    const itemsPerPage = ref(5);
    const currentPage = ref(1);

    const paginatedItems = computed(() => {
      const start = (currentPage.value - 1) * itemsPerPage.value;
      const end = start + itemsPerPage.value;
      return items.value.slice(start, end);
    });

    const handlePageChange = (newPage) => {
      currentPage.value = newPage;
    };

    return {
      items,
      itemsPerPage,
      currentPage,
      paginatedItems,
      handlePageChange,
    };
  },
};
</script>

5. 总结

通过以上步骤,我们成功地在Vue中自定义了一个翻页组件。这个组件不仅支持基本的上一页、下一页功能,还支持直接跳转到指定页码,并且能够根据总页数动态调整显示的页码数量。通过emit事件,父组件可以轻松地响应页码的变化,从而实现数据的动态加载。

在实际项目中,您可以根据需求进一步扩展这个组件,例如添加更多的样式、支持不同的分页布局、或者与其他UI库集成。希望本文能够帮助您更好地理解如何在Vue中自定义翻页组件,并为您的项目开发提供有价值的参考。

推荐阅读:
  1. vue自定义分页组件案例
  2. 如何使用vue中实现翻页组件vue-flip-page效果

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue

上一篇:uniapp小程序如何配置tabbar底部导航栏

下一篇:JS实现单例模式的方式有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》