node使用Promise.all一次返回分页列表及记录总数axios每页请求Vue分页查询(包括页查询组件封装模板+逻辑)

分页查询常见3种思路

  • 客户端分页:直接获取所有数据返回给客户端,客户端通过展示组件进行数据分页控制。
  • 数据库分页:数据库查询时,返回一页的数据以及总记录数。
  • 服务器分页:从数据库获取所有数据服务器进行缓存,每次返回一页数据给客户端。

数据库分页

这就意味着,每次客户端切换页码时,都要查询数据库获取一页数据。同时,客户端也需要知道记录总数,以便分页组件得到页数。以下列出具体代码,详情在注释中解释。

客户端
  1. 分页组件:
    在这里插入图片描述
    pkk-pagination.vue 组件代码:[ 太长了,贴在最后 ]

  2. 使用组件代码:

  • 第一条结果在data.list[0]
  • 第二条结果在data.list[1],sql中count(0)取了别名total,所以结果总数在data.list[1][0].total
	<!-- 使用组件,省略其他模板代码 -->
	<PkkPagination
        @current-change="changePager"
        :total="total"
        :currentPage="reqParams.page"
      />
    <!-- 使用组件,省略其他模板代码 -->

	<!-- Vue3 的Setup部分 -->
	setup() {
    // 筛选条件准备
    const reqParams = reactive({
      page: 1,
      pageSize: 12,
    });
    const productList = ref([]); //记录所有商品信息
    const total = ref(0); //记录总条数
    
    watch(
      reqParams,
      async () => {
        const data = await getProductByCateId(
          1001,
          reqParams.page,
          reqParams.pageSize
        );
        //服务器返回两条结果,由数组包裹,具体log一下查看返回的结果
        //第一条结果在data.list[0]
        //第二条结果在data.list[1],sql中count(0)取了别名total,所以结果总数在data.list[1][0].total
        productList.value = data.list[0];
        total.value = data.list[1][0].total;
      },
      { immediate: true }
    );

    // 改变分页函数,接收子组件传来的参数:当前页码
    const changePager = (np) => {
      // 改变页数
      reqParams.page = np;
    };

    return { reqParams, productList, total, changePager };
  }
  1. axios请求代码:
  • 此处已封装了axios,暴露出了request,封装代码贴在后面
  • 传递数据库分页所需参数
  • cate_id:是某一分类id,作为where条件筛选
  • curr_page:是当前页
  • page_size:是每页数量
  • 数据库查询中limit n,m :n是起始记录数,m是获取多少条,n = (curr_page-1)*page_size
/**
 * 获取所有商品信息
 * 此处已封装了axios,暴露出了request,封装代码贴在后面
 * 传递数据库分页所需参数
 * cate_id:是某一分类id,作为where条件筛选
 * curr_page:是当前页
 * page_size:是每页数量
 * 数据库查询中limit n,m :n是起始记录数,m是获取多少条,n = (curr_page-1)*page_size
*/
export const getProductByCateId = (cate_id,curr_page,page_size) => {
  return request('/category/products', 'get',{cate_id,curr_page,page_size})
}

服务器(nodejs、express)、数据库

  1. 设置接口:‘/category/products’

  2. categroy_dao.js 关于数据库的请问文件

  • 定义两次数据库请求
  • 将多个Promise实例包装称一个新的Promise实例,返回一个res
/**
   * 
   * @param {*} cateId 类目id
   * @param {*} currPage 当前页码
   * @param {*} pageSize 每页数量
   * @returns 
   */
  static queryProdsByCateId(cateId,currPage,pageSize){
    let start = (currPage-1)*pageSize; //计算起始记录数
    //使用模板字符串插入变量
    //需要两次数据库查询,写两条sql语句
    let sql = `SELECT * FROM pin_product WHERE pro_category_id=${cateId} limit ${start},${pageSize};`;
    let sql2 = `SELECT COUNT(*) total FROM pin_product WHERE pro_category_id=${cateId};`;

	//定义第一次数据库请求
    const P1 = new Promise((resolve, reject) => {
      this.query(sql).then(res => {
        resolve(res)
      }).catch(err=>{
        reject(err)
      })
    })

	//定义第二次数据库请求
    const P2 = new Promise((resolve, reject) => {
      this.query(sql2).then(res => {
        resolve(res)
      }).catch(err=>{
        reject(err)
      })
    })
	//将多个Promise实例包装称一个新的Promise实例,返回一个res
    return Promise.all([P1,P2])
  }
  1. cetegory.js 关于数据处理的文件
  • 客户端将会收到一个数组,成员包含两个Promise返回的数据,{list: Array(2)}
/* 获取某一分类的所有商品 */
  static async getProdsByCateId(req,res){
    let cateId = parseInt(req.query.cate_id);
    let currPage = parseInt(req.query.curr_page);
    let pageSize = parseInt(req.query.page_size);

	//返回数据给客户端
	//客户端将会收到一个数组,成员包含两个Promise返回的数据,{list: Array(2)}
    let result = await this.queryProdsByCateId(cateId,currPage,pageSize);

    res.json({list:result})
  }

附页代码

pkk-pagination.vue 组件代码
<template>
  <div class="pkk-pagination">
    <a v-if="myCurrentPage <= 1" href="javascript:;" class="disabled">上一页</a>
    <a @click="changePage(myCurrentPage - 1)" v-else href="javascript:;"
      >上一页</a
    >
    <span v-if="pager.start > 1">...</span>
    <a
      @click="changePage(i)"
      href="javascript:;"
      :class="{ active: i === myCurrentPage }"
      v-for="i in pager.btnArr"
      :key="i"
      >{{ i }}</a
    >
    <span v-if="pager.end < pager.pageCount">...</span>
    <a
      v-if="myCurrentPage >= pager.pageCount"
      href="javascript:;"
      class="disabled"
      >下一页</a
    >
    <a @click="changePage(myCurrentPage + 1)" v-else href="javascript:;"
      >下一页</a
    >
  </div>
</template>

<script>
import { ref, computed, watch } from "vue";
export default {
  name: "PkkPagination",
  props: {
    total: {
      type: Number,
      default: 100,
    },
    currentPage: {
      type: Number,
      default: 1,
    },
    pageSize: {
      type: Number,
      default: 10,
    },
  },
  setup(props,{emit}) {
    //总条数
    const myTotal = ref(100);
    //每页条数
    const myPageSize = ref(10);
    //当前第几页
    const myCurrentPage = ref(5);
    //按钮个数
    const btnCount = 5;

    const pager = computed(() => {
      //计算总页数
      const pageCount = Math.ceil(myTotal.value / myPageSize.value);
      // 计算起始页码和结束页码
      // 1. 理想情况根据当前页码,和按钮个数可得到
      let start = myCurrentPage.value - Math.floor(btnCount / 2);
      let end = start + btnCount - 1;
      // 2.1 如果起始页码小于1了,需要重新计算
      if (start < 1) {
        start = 1;
        end =
          start + btnCount - 1 > pageCount ? pageCount : start + btnCount - 1;
      }
      // 2.2 如果结束页码大于总页数,需要重新计算
      if (end > pageCount) {
        end = pageCount;
        start = end - btnCount + 1 < 1 ? 1 : end - btnCount + 1;
      }
      // 处理完毕start和end得到按钮数组
      const btnArr = [];
      for (let i = start; i <= end; i++) {
        btnArr.push(i);
      }
      return { pageCount, start, end, btnArr };
    });

    //改变页码
    const changePage = (newPage) => {
      if (myCurrentPage.value !== newPage) {
        myCurrentPage.value = newPage;
        // 通知父组件最新页码
        emit("current-change", newPage);
      }
    };

    // 监听传入的值改变
    watch(
      props,
      () => {
        myTotal.value = props.total;
        myPageSize.value = props.pageSize;
        myCurrentPage.value = props.currentPage;
      },
      { immediate: true }
    );
    return { pager, myCurrentPage, changePage };
  },
};
</script>

<style scoped lang="less">
.pkk-pagination {
  display: flex;
  justify-content: center;
  padding: 30px;
  > a {
    display: inline-block;
    padding: 5px 10px;
    border: 1px solid #e4e4e4;
    border-radius: 4px;
    margin-right: 10px;
    &:hover {
      color: @pkkColor;
    }
    &.disabled {
      cursor: not-allowed;
      opacity: 0.4;
      &:hover {
        color: #333;
      }
    }
    &.active {
      background: @pkkColor;
      color: #fff;
      border-color: @pkkColor;
    }
  }
  > span {
    margin-right: 10px;
  }
}
</style>

axios封装代码
// 1. 创建一个新的axios实例
// 2. 请求拦截器,如果有token进行头部携带
// 3. 响应拦截器:1. 剥离无效数据  2. 处理token失效
// 4. 导出一个函数,调用当前的axsio实例发请求,返回值promise
import axios from 'axios'
import store from '@/store'
import router from '@/router'
// 导出基准地址,原因:其他地方不是通过axios发请求的地方用上基准地址
export const baseURL = 'http://localhost:3000/'
const instance = axios.create({
  // axios 的一些配置,baseURL  timeout
  baseURL,
  timeout: 10000
})
instance.interceptors.request.use(config => {
  // 拦截业务逻辑
  return config
}, err => {
  return Promise.reject(err)
})
// res => res.data  取出data数据,将来调用接口的时候直接拿到的就是后台的数据
instance.interceptors.response.use(res => res.data, err => {
  return Promise.reject(err)
})
// 请求工具函数
export default (url, method, submitData) => {
  // 负责发请求:请求地址,请求方式,提交的数据
  return instance({
    url,
    method,
    // 1. 如果是get请求  需要使用params来传递submitData   ?a=10&c=10
    // 2. 如果不是get请求  需要使用data来传递submitData   请求体传参
    // [] 设置一个动态的key, 写js表达式,js表达式的执行结果当作KEY
    // method参数:get,Get,GET  转换成小写再来判断
    // 在对象,['params']:submitData ===== params:submitData 这样理解
    [method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
  })
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Vue3 TS Axios Route Element Plus 可二次开发的模板,是一款帮助开发人员更快速、高效地完成项目搭建的工具。它集成了Vue3、TypeScript、AxiosVue Router、Element Plus等主流技术,采用优雅的代码风格和完美封装的方式,让开发工作更加轻松愉快。 这个模板具有强大的请求功能,可以轻松实现请求的拦截、响应统一处理等,大大提高了开发效率。具体的请求使用方法可以参考官方文档,使用简单,易于上手。 此外,这个模板还采用了Vue Router路由管理,能够实现页面间的无缝切换、动态路由绑定等功能,为项目的前端路由管理提供了很好的支持。 另外,Element Plus UI组件库的集成,让开发人员可以使用丰富多彩、易于定制的UI组件,从而更加轻松快捷地完成页面的搭建工作。 总的来说,Vue3 TS Axios Route Element Plus 可二次开发的模板是一款非常优秀的工具,它的使用可以大大提高开发效率,让开发工作更加轻松、快捷。如果你正在寻找一款高效、易用、可定制化的项目模板,那么这个模板将会是一个非常不错的选择。 ### 回答2: Vue3 TS Axios Route Element Plus 可二次开发的模板是一个非常好用的前端模板,它包含了一系列完美封装的工具和组件,让前端开发变得更加快捷高效。 对于请求使用方法,模板采用了 axios 进行请求的发送和拦截,可以通过在相关文件中配置 baseURL、headers、timeout 等信息来进行设置。同时,针对不同的请求接口,模板提供了多种不同的请求类别,包括 GET、POST、PUT、DELETE 等,使用起来非常灵活方便。 在封装方面,模板对 Element Plus 组件库进行了二次封装,让组件使用更加简便。同时,对于一些常见的业务组件模板也进行了封装,例如表格组件、表单组件、分页组件等,可以基本满足大多数前端开发的需求。 总体而言,Vue3 TS Axios Route Element Plus 可二次开发的模板非常适合中小型项目的快速开发,同时也具备较高的可定制性和扩展性,非常推荐大家去尝试使用。 ### 回答3: Vue3 TS Axios Route Element Plus 可二次开发的模板是一个非常有用的工具,它可以帮助开发者快速搭建一个高效、可靠的Vue3项目。该模板包括请求使用方法、完美封装,可以满足绝大部分前端项目的需求。 首先,该模板使用Vue3作为前端框架,集成了TypeScript类型检查工具,可以提升开发效率和代码质量。Axios作为HTTP请求库,是一个非常常用的工具,可以轻松地处理前端的数据请求。而Route则是Vue3中的路由管理工具,提供路由拦截、跳转等多种功能,便于前端项目的开发。 此外,该模板还集成了Element Plus作为UI框架,可支持更丰富的UI组件,提供多样化的视觉效果和交互视频。使用Element Plus可以使得开发者在UI设计上节省大量时间,让开发工作更加高效。 最重要的是,该模板为以上工具进行了二次开发,使其更加适合前端项目的需求。在对数据请求封装上,该模板采用了Promise的设计模式,可以方便地进行链式调用,提升代码的可读性。同时,该模板还支持多种请求方式,例如GET、POST等,可以赋予前端更多的开发空间。 总的来说,Vue3 TS Axios Route Element Plus 可二次开发的模板是一个非常实用的工具,在前端项目开发中,它可以大大提升开发效率和代码质量,让前端开发者更加专注于需求实现本身,而非底层细节的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值