【uniapp】实现触底加载数据

news2024/10/17 10:18:55

前言:实现界面触底数据加载。后端接口得支持翻页传参(本案例使用django)

1、后端接口 

1.1 封装翻页公共方法standardPagination.py

# -*- coding: utf-8 -*-
# @Time    : 2024/10/15 13:15
# @Author  : super
# @File    : standardPagination.py
# @Software: PyCharm
# @Describe:

from rest_framework.pagination import PageNumberPagination
# 定义分页类,可以自定义每页显示的记录数
class StandardResultsSetPagination(PageNumberPagination):
    page_size = 10  # 每页显示的记录数,可以根据需要调整
    page_size_query_param = 'page_size'  # 允许客户端通过此参数指定每页显示的记录数
    max_page_size = 100  # 最大每页显示的记录数,防止客户端请求过多数据

1.2 views代码

支持按标题进行查询

class HonorExperienceSet(ModelViewSet):
    queryset = HonorExperience.objects.all().order_by('-date_earned','-create_time')
    serializer_class = HonorExperienceSerializer
    pagination_class = StandardResultsSetPagination  # 设置分页类
    def get_queryset(self):
        queryset = super().get_queryset()
        title = self.request.query_params.get('title', None)
        if title is not None:
            queryset = queryset.filter(title__icontains=title)
        return queryset

 2、uniapp方法

2.1 页面支持数据查询 

页面可进行查询,然后导入onReachBottom

<template>
<view class="pageBg" >

  <view class="header">
    <!-- 搜索框 -->
    <input type="text" v-model="searchQuery" placeholder="搜索荣誉标题" class="search-input" />

    <!-- 确定按钮 -->
    <button @click="searchHonor" class="search-button">
      <image src="/static/images/honorWall/ss.png" class="search-icon" />
    </button>

    <!-- 新增按钮 -->
	<navigator url="/pages/addHonor/addHonor">
		<button class="add-button">
		  <image src="/static/images/honorWall/add.png" class="add-icon" />
		</button>
	</navigator>
    
  </view>

  <!-- 列表展示 -->
  <view v-if="honorList.length > 0" class="honor-list">
    <view v-for="(item,index) in honorList" :key="item.id"  class="honor-item">
		 <text>{{ index + 1 }}</text>  
      <text>{{ item.type_display }}</text>
      <text>{{ item.title }}</text>
      <text>{{ formatDate(item.date_earned) }}</text>
    </view>
  </view>  


  <!-- 无数据时的占位提示 -->
  <view v-else class="no-data">
    <text>暂无荣誉数据</text>
  </view>
	
</view>
</template>

<script setup>
import { api } from '../../config/settings';
import { ref, onMounted, watch } from 'vue';
import {onReachBottom} from '@dcloudio/uni-app';
import {apiFetchHonorData} from '@/api/apis.js';
import { useRouter } from 'vue-router';


// 定义存储荣誉数据的变量
const honorList = ref([]);

// 查询条件
const searchQuery = ref('');
// 定义请求参数,title 参数如果没有提供,默认为 null
const params = ref({
  title: '', // 不传 title 参数时,接口将不过滤 title
  page: 1,   // 页码
  page_size: 20 // 每页显示的记录数
});

// 格式化日期的方法
const formatDate = (dateStr) => {
  const date = new Date(dateStr);
  return `${date.getFullYear()}-${('0' + (date.getMonth() + 1)).slice(-2)}-${('0' + date.getDate()).slice(-2)}`;
};

  
// 默认查询
const fetchHonorData = async () => {  
	// console.log(params);
  try {  
    const res = await apiFetchHonorData(params.value); // 初始加载时不带查询条件  
    honorList.value = res.data.results || []; // 确保即使响应中没有 data 字段,honorList 也是一个数组  
	
  } catch (error) {  
    console.error('组件挂载时获取荣誉数据失败:', error);  
    // 可以选择在这里处理错误,比如显示一个错误消息  
  }  
}
//挂载时执行默认查询
onMounted(fetchHonorData);  
//  搜索查询 
const searchHonor = async () => {
	// 更新 params 的 title 值
	params.value.title = searchQuery.value;
	// console.log(params.value);
  try {  
    const res = await apiFetchHonorData(params.value);  
    honorList.value = res.data.results  || []; // 更新荣誉列表 

  } catch (error) {  
    console.error('搜索荣誉数据时失败:', error);  
    // 可以选择在这里处理错误,比如显示一个错误消息或重置查询框  
  }  
};  

onReachBottom(()=>{	
	
	console.log("sss")
})

</script>

<style lang="scss" scoped>
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  // margin-bottom: 5px;
}

.search-input {
  flex-grow: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.search-button {
  display: flex;
  align-items: center;
  color: white;
  border: none;
  border-radius: 5px;
  padding: 10px;
  cursor: pointer;
}

.search-icon {
  width: 24px;
  height: 24px;
}

.add-button {
  display: flex;
  align-items: center;
  color: white;
  border: none;
  border-radius: 5px;
  padding: 10px;
  cursor: pointer;
}

.add-icon {
  width: 24px;
  height: 24px;
}

.honor-list {
  padding: 5px;
}

// .honor-item {
//   display: flex;
//   justify-content: space-between;
//   border-bottom: 1px solid #ddd;
//   padding: 10px 0;
// }
.honor-item {  
  display: flex;  
  align-items: center; // 确保所有子元素垂直居中  
  border-bottom: 1px solid #ddd;  
  padding: 10px 0;  
}  
  
.honor-item > text:nth-child(1) { // 序号列  
  width: 40px; // 固定宽度  
  text-align: center;  
}  
  
.honor-item > text:nth-child(2) { // 类型显示列  
  width: 60px; // 根据内容调整或固定宽度  
  text-align: left; // 或根据需求调整  
}  
  
.honor-item > text:nth-child(3) { // 标题列  
  flex-grow: 1; // 填充剩余空间  
  min-width: 0; // 允许收缩到内容的最小宽度  
  white-space: nowrap; // 防止文本换行  
  overflow: hidden; // 隐藏溢出内容  
  text-overflow: ellipsis; // 使用省略号表示溢出文本  
  margin: 0 10px; // 可选:增加左右间距以改善可读性 

}  
  
.honor-item > text:nth-child(4) { // 日期列  
  width: 120px; // 固定宽度  
  text-align: right; // 根据需求调整  
}

.no-data {
  text-align: center;
  padding: 20px;
  color: #999;
}
</style>

2.2 添加实现触底翻页查询

onReachBottom(()=>{
	
	params.value.page++;
	fetchHonorData();
	console.log("sss")
})

2.3 实现数据触底拼接

honorList.value = [...honorList.value, ...res.data.results] || []; // 更新荣誉列表 

2.4 解决数据加载完毕还执行查询问题

//定义获取不到数据的处理
const noDate = ref(false)


#此位置加入如下代码

 honorList.value = [...honorList.value, ...res.data.results] || []; // 确保即使响应中没有 data 字段,honorList 也是一个数组  
	if(params.value.page_size > res.data.results.length) noDate.value = true;


# 加判断
onReachBottom(()=>{
	if(noDate.value
	) return;
	params.value.page++;
	fetchHonorData();
	console.log("sss")
})

2.5 完整代码

<template>
<view class="pageBg" >

  <view class="header">
    <!-- 搜索框 -->
    <input type="text" v-model="searchQuery" placeholder="搜索荣誉标题" class="search-input" />

    <!-- 确定按钮 -->
    <button @click="searchHonor" class="search-button">
      <image src="/static/images/honorWall/ss.png" class="search-icon" />
    </button>

    <!-- 新增按钮 -->
	<navigator url="/pages/addHonor/addHonor">
		<button class="add-button">
		  <image src="/static/images/honorWall/add.png" class="add-icon" />
		</button>
	</navigator>
    
  </view>

  <!-- 列表展示 -->
  <view v-if="honorList.length > 0" class="honor-list">
    <view v-for="(item,index) in honorList" :key="item.id"  class="honor-item">
		 <text>{{ index + 1 }}</text>  
      <text>{{ item.type_display }}</text>
      <text>{{ item.title }}</text>
      <text>{{ formatDate(item.date_earned) }}</text>
    </view>
  </view>  


  <!-- 无数据时的占位提示 -->
  <view v-else class="no-data">
    <text>暂无荣誉数据</text>
  </view>
	
</view>
</template>

<script setup>
import { api } from '../../config/settings';
import { ref, onMounted, watch } from 'vue';
import {onReachBottom} from '@dcloudio/uni-app';
import {apiFetchHonorData} from '@/api/apis.js';
import { useRouter } from 'vue-router';

//定义获取不到数据的处理
const noDate = ref(false)
// 定义存储荣誉数据的变量
const honorList = ref([]);

// 查询条件
const searchQuery = ref('');
// 定义请求参数,title 参数如果没有提供,默认为 null
const params = ref({
  title: '', // 不传 title 参数时,接口将不过滤 title
  page: 1,   // 页码
  page_size: 20 // 每页显示的记录数
});

// 格式化日期的方法
const formatDate = (dateStr) => {
  const date = new Date(dateStr);
  return `${date.getFullYear()}-${('0' + (date.getMonth() + 1)).slice(-2)}-${('0' + date.getDate()).slice(-2)}`;
};

  
// 默认查询
const fetchHonorData = async () => {  
	// console.log(params);
  try {  
    const res = await apiFetchHonorData(params.value); // 初始加载时不带查询条件  
    honorList.value = [...honorList.value, ...res.data.results] || []; // 确保即使响应中没有 data 字段,honorList 也是一个数组  
	if(params.value.page_size > res.data.results.length) noDate.value = true;
  } catch (error) {  
    console.error('组件挂载时获取荣誉数据失败:', error);  
    // 可以选择在这里处理错误,比如显示一个错误消息  
  }  
}
//挂载时执行默认查询
onMounted(fetchHonorData);  
//  搜索查询 
const searchHonor = async () => {
	// 更新 params 的 title 值
	params.value.title = searchQuery.value;
	// console.log(params.value);
  try {  
    const res = await apiFetchHonorData(params.value);  
    honorList.value = [...honorList.value, ...res.data.results] || []; // 更新荣誉列表 
	 if(params.value.page_size > res.data.results.length) noDate.value = true;
  } catch (error) {  
    console.error('搜索荣誉数据时失败:', error);  
    // 可以选择在这里处理错误,比如显示一个错误消息或重置查询框  
  }  
};  

onReachBottom(()=>{
	if(noDate.value
	) return;
	params.value.page++;
	fetchHonorData();
	console.log("sss")
})

</script>

<style lang="scss" scoped>
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  // margin-bottom: 5px;
}

.search-input {
  flex-grow: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.search-button {
  display: flex;
  align-items: center;
  color: white;
  border: none;
  border-radius: 5px;
  padding: 10px;
  cursor: pointer;
}

.search-icon {
  width: 24px;
  height: 24px;
}

.add-button {
  display: flex;
  align-items: center;
  color: white;
  border: none;
  border-radius: 5px;
  padding: 10px;
  cursor: pointer;
}

.add-icon {
  width: 24px;
  height: 24px;
}

.honor-list {
  padding: 5px;
}

// .honor-item {
//   display: flex;
//   justify-content: space-between;
//   border-bottom: 1px solid #ddd;
//   padding: 10px 0;
// }
.honor-item {  
  display: flex;  
  align-items: center; // 确保所有子元素垂直居中  
  border-bottom: 1px solid #ddd;  
  padding: 10px 0;  
}  
  
.honor-item > text:nth-child(1) { // 序号列  
  width: 40px; // 固定宽度  
  text-align: center;  
}  
  
.honor-item > text:nth-child(2) { // 类型显示列  
  width: 60px; // 根据内容调整或固定宽度  
  text-align: left; // 或根据需求调整  
}  
  
.honor-item > text:nth-child(3) { // 标题列  
  flex-grow: 1; // 填充剩余空间  
  min-width: 0; // 允许收缩到内容的最小宽度  
  white-space: nowrap; // 防止文本换行  
  overflow: hidden; // 隐藏溢出内容  
  text-overflow: ellipsis; // 使用省略号表示溢出文本  
  margin: 0 10px; // 可选:增加左右间距以改善可读性 

}  
  
.honor-item > text:nth-child(4) { // 日期列  
  width: 120px; // 固定宽度  
  text-align: right; // 根据需求调整  
}

.no-data {
  text-align: center;
  padding: 20px;
  color: #999;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2216980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea2024年版本

最简单安装2024.2版本idea 内带安装教程 ** 下载链接&#xff1a;https://pan.quark.cn/s/ab24afbaa43f 提取码&#xff1a;KHrq

《计算机视觉》—— 基于PyCharm中的dlib库实现人脸关键点定位

文章目录 1. 安装必要的库2. 下载dlib的人脸检测器和关键点预测器模型3. 编写代码 人脸关键点定位是指通过计算机视觉技术&#xff0c;识别和定位人脸图像中的关键点&#xff0c;如眼睛、鼻子、嘴巴等特定位置。这些关键点的准确定位对于人脸识别、表情分析、姿态估计等应用具有…

天地伟业NVR管理工具EasyNVR平台多个NVR同时管理运行后日志一直在打印error

视频安防监控平台天地伟业NVR管理工具EasyNVR可支持设备通过RTSP/Onvif协议接入&#xff0c;并能对接入的视频流进行处理与多端分发&#xff0c;包括RTMP、RTSP、WS-FLV、HTTP-FLV、WebRTC、HLS等多种视频流格式。平台可提供视频实时监控直播、云端录像、录像检索、云存储与回看…

基于SSM的药品商城系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

沉浸式娱乐新纪元,什么是5G+实时云渲染VR大空间?

近年来&#xff0c;虚拟现实&#xff08;VR&#xff09;技术在娱乐、教育、医疗等多个领域展现出巨大的潜力&#xff0c;尤其是VR大空间体验&#xff0c;更是以其沉浸式和互动性的特点&#xff0c;迅速成为市场的新宠。据Statista数据显示&#xff0c;2023年&#xff0c;全球虚…

Lumerical学习——资源管理和运行模拟

一、资源管理&#xff08;Resource Manager&#xff09; 在模拟计算前必须对计算资源进行配置。采用资源管理器可以完成这项任务。单击主工具条的“资源&#xff08;Resources&#xff09;”按钮&#xff08;见上图&#xff09;就可以打开资源管理器。通常每个计算机只需设置一…

【含文档】基于Springboot+Vue的仓库管理系统设计与实现(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

JAVA基础【第二篇】

文章目录 类变量介绍语法代码示例 类方法介绍注意事项代码示例 代码块介绍基本语法注意事项 设计模式单例设计模式介绍饿汉式懒汉式两者区别 模板设计模式介绍代码示例 final关键字介绍代码示例注意事项 抽象类介绍注意事项 接口介绍基本语法注意细节接口特性 内部类介绍分类局…

深入理解 KMP 算法

《深入理解 KMP 算法》 在计算机科学中&#xff0c;字符串匹配是一个常见且重要的问题&#xff0c;而 KMP&#xff08;Knuth - Morris - Pratt&#xff09;算法则是一种高效的字符串匹配算法。 一、KMP 算法的背景 在传统的字符串匹配算法中&#xff0c;当遇到不匹配的字符时…

基于AES的遥感图像加密算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 AES 加密算法概述 4.2 基于 AES 的遥感图像加密算法原理 5.完整程序 1.程序功能描述 通过AES算法对遥感图像进行加密和解密&#xff0c;分析加解密处理后图像的直方图&#xff0c;相关…

React之组件渲染性能优化

关键词&#xff1a; shouldComponentUpdate、PureComnent、React.memo、useMemo、useCallback shouldComponentUpdate 与 PureComnent shouldComponentUpdate 与 PureComnent 用于类组件。虽然官方推荐使用函数组件&#xff0c;但我们依然需要对类组件的渲染优化策略有所了解…

jar 导入本地和远程私服 maven 仓库

jar 导入本地和远程私服 maven 仓库artemis-http-client 认证库 maven 坐标为&#xff1a; 执行 mvn 命令&#xff1a; mvn install:install-file -DfileD:\download\lib\artemis-http-client-1.1.12.RELEASE.jar -DgroupIdcom.hikvision.ga -DartifactIdartemis-http-clien…

图像中的融合

图像显示函数 def img_show(name, img):"""显示图片:param name: 窗口名字:param img: 图片对象:return: None"""cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()图像读取与处理 读取图片 cloud cv2.imread(bg.jpg) fish cv2.…

C++ | Leetcode C++题解之第485题最大连续1的个数

题目&#xff1a; 题解&#xff1a; class Solution { public:int findMaxConsecutiveOnes(vector<int>& nums) {int maxCount 0, count 0;int n nums.size();for (int i 0; i < n; i) {if (nums[i] 1) {count;} else {maxCount max(maxCount, count);coun…

【二刷hot-100】day1

目录 1.两数之和 2.字母异位词分组 3.字母异位词分组 4.最长连续序列 5.移动零 6.盛最多水的容器 7.三数之和 8.接雨水 1.两数之和 class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> mapnew HashMap<>();for (int i0;i<…

10.16标准IO

1、完成标准IO的单字符、字符串、格式化、模块化实现两个文件的拷贝&#xff1b; 单字符实现 #include <myhead.h> int main(int argc, const char *argv[]) {//使用单字符完成两个文件拷贝FILE *fp_srcfopen(argv[1],"r");FILE *fp_destfopen(argv[2],"…

猪圈密码简单实例

猪圈密码简单实例 猪圈密码表 根据上面的密码表&#xff0c;得到每个字母所对应的符号如下 例如单词the的加密结果为&#xff1a;

IO编程--单字符、字符串、格式化、模块化实现文件拷贝以及登录注册

一、完成标准io的单字符、字符串、格式化、模块化实现两个文件的拷贝 代码如下&#xff1a; 1.单字符 #include <myhead.h> int main(int argc, const char *argv[]) {//打开文件FILE* fpfopen("test.txt","r"); FILE* fqfopen("copy_test.txt&…

leetcode:744. 寻找比目标字母大的最小字母(python3解法)

难度&#xff1a;简单 给你一个字符数组 letters&#xff0c;该数组按非递减顺序排序&#xff0c;以及一个字符 target。letters 里至少有两个不同的字符。 返回 letters 中大于 target 的最小的字符。如果不存在这样的字符&#xff0c;则返回 letters 的第一个字符。 示例 1&a…

2024国际潜水小姐大赛中国区总决赛盛典在广州举行,吉林选手张潇文获冠军!

传承“以美之名&#xff0c;保护海洋”的精神&#xff0c;2024年10月15日晚&#xff0c;2024国际潜水小姐大赛中国区总决赛盛典在广州渔民新村隆重举行&#xff01;来自全国多个城市&#xff0c;经过层层选拔产生的20位佳丽齐聚广州&#xff0c;以独特的女性水下之美和健康美&a…