uniapp(下拉刷新+上拉加载)---通俗易懂且代码可直接复制

开发时间:2024/09/15

开发作者:zhaozzz

开发工具:uniapp开发微信小程序

好久没写博客了,最近挺忙的,要看论文,要找方向。更新一下最近遇到的问题把。

1.实现加载分页+下拉刷新+上拉加载

只需要改一下接口和属性名,其他的全部复制粘贴,就可以使用,我已经帮大家测试过了喔~

欢迎大家来交流哦

1.实现加载分页 。我使用了uview中的---loadMore 加载更多组件  点击跳转 

我先来展示一下我的界面,看是否对您有帮助呢?

上拉加载界面+下拉刷新界面 

HTML界面

    <view class="wrap">
        <view class="item u-border-bottom" v-for="(item, index) in list" :key="index">
          <view class="main_toalbox" @click="toTeacherResume(item.teacherId)">
            <view class="main-box">
              <view class="main-box_1">
                <ul>
                  <li>
                    <u-avatar 
					:show-sex="true"
					:sex-icon="getSexIcon(item.teacherGender)" 
					:src="`${BASE_URL}${item.teacherAvatar}`"></u-avatar>
                  </li>
                  <li style="font-size: 12px;color: #999999;">最近登录</li>
                  <li style="padding-left: 10px;font-size: 12px;color: #999999;">今天</li>
                </ul>
              </view>
              <view class="main-box_2">
                <ul>
                  <li class="li_1">
                    <span>{{ getTeacherLabel(item.teacherName)}}</span>
                  </li>
                  <li class="li_2">
                    <span
                      style="
                      display: inline-block;
                      margin-left: 0px;
                      margin-top: 8px;
                      width: 25px;
                      margin-right: 5px;
                      text-align: center;
                      border-radius: 5px;
                      background-color: #6e7ac2;
                      color: #ffffff;">{{ item.teacherGender }}</span>
                    <span style="
                      width: 80px;
                      display: inline-block;
                      margin-right: 7px;
                      text-align: center;
                      border-radius: 5px;
                      background-color: #6e7ac2;
                      color: #ffffff;
                      margin-top: 8px;
                    "
                    >{{ item.starRating }}</span>
                    <span style="
                      color: #fa7409;
                      background-color: #ffffff;
                      border: 1px solid #fa7409;
                      margin-top: 8px;
                      border-radius: 5px;
					  padding-left: 5px;
					  padding-right: 5px;">{{ item.university }}</span>
                  </li>
                  <li class="li_3" style="margin-top: 8px;">
                    <span style="color: black;">家教区域:</span>
                    <span v-for="(area,index) in splitAreas(item.teachingArea)" :key="index" class="area-label">
                      {{area}}
                    </span>
                    <span v-if="item.teachingArea.split(',').length > 3"></span>
                  </li>
                  <li class="li_4" style="margin-top: 8px;">
                    <span style="color: black;">家教科目:</span>
                    <span v-for="(subject, index) in displayedSubjects(item.tutoringSubjects)" :key="index" class="subject-label">
                      {{ subject }}
                    </span>
                  </li>
                </ul>
              </view>
            </view>
          </view>
        </view>
        <u-loadmore :status="status" style="margin-top: 20px;" /> //使用组件开发
      </view>

JS界面 

<script>
import { getTutorList } from "@/api/getTutorList.js"; //引入获取数据的接口
import { BASE_URL } from "@/static/js/data.js";  //方便修改服务器地址
export default {
  data() {
    return {
      status: 'loadmore',// 组件状态,指的是加载更多
      list: [],//存放数据
      current: 1, //当前页
      pageSize: 5,//页面大小
	  showTotal: true, //是否显示“下拉加载更多~”
	  BASE_URL, //方便修改服务器地址 同一写到一个data.js中
	   selectedGender: '',
			selectedGenderLabel: '性别',
				selectedStar: '',
				selectedStarLabel: '星级',
				selectedCity: '',
				selectedCityLabel: '城市',
				selectedSubject: '',
				selectedSubjectLabel: '科目',
    };
  },
  methods: {
   //因为头像组件的值是man/woman 但是我接收到数据是男/女 所以这里要调整一下
	getSexIcon(teacherGender){
					return  teacherGender ==='女'? 'woman' : 'man'
				},
			splitAreas(teachingArea) {
			    // 确保传入的是一个字符串,否则返回空数组
			    if (!teachingArea || typeof teachingArea !== 'string') return [];
			
			    // 将字符串按逗号分割为数组
			    const areaArray = teachingArea.split(',');
			
			    // 如果区域数量超过3个,展示前三个并加上'...'
			    if (areaArray.length > 3) {
			      return areaArray.slice(0, 3);
			    }
			
			    // 否则直接展示全部区域
			    return areaArray;
			  },
			 getTeacherLabel(name) {
			   if (name && name.length > 0) {
			     // 取姓名的第一个字并加上"教员"
			     return name.charAt(0) + '教员';
			   }
			   return '教员'; // 如果名字为空,默认显示"教员"
			 },
			 displayedSubjects(subjects) {
			   // 将字符串按逗号分割为数组
			   const subjectArray = subjects.split(',');
			   
			   // 如果科目数量超过3个,展示前三个并加上'...'
			   if (subjectArray.length > 3) {
			     return [...subjectArray.slice(0, 3)];
			   }
			   // 否则直接展示全部科目
			   return subjectArray;
			 },
			//因为头像组件的值是man/woman 但是我接收到数据是男/女 所以这里要调整一下
			getSexIcon(teacherGender) {
				return teacherGender === '女' ? 'woman' : 'man'
			},
search() {
				this.status = 'loadmore';
				this.list = [];
				this.current = 1;
				this.findData();
			},
  //获取数据
    findData() {
     //当我查找到具体内容后,我想返回全部内容时,这里是用来返回全部 
	const tutoringSubjects = this.selectedSubject === '科目' ? '' : this.selectedSubject;
	const tutoringStar = this.selectedStar === '不限' ? '' : this.selectedStar;
	const tutoringCity = this.selectedCity === '全部' ? '' : this.selectedCity;
	const tutoringGender =this.selectedGender === '不限' ? '' : this.selectedGender;
	//根据不同接口,写上需要传输的参数 
      const params = {
        current: this.current,
        pageSize: this.pageSize,
        teaching_area:tutoringCity,
        teacher_gender: tutoringGender,
        star_rating: tutoringStar,
        current_address: '',
        tutoring_subjects: tutoringSubjects 
      };
      console.log('Params:', params); // 打印筛选条件
      uni.showToast({
          title: '加载中',
          icon: 'loading',
          duration: 1000 // 1秒后自动消失
        });
         setTimeout(() => {
             getTutorList(params).then(res => {
               console.log('Response:', res);
               const data = res.tutors || [];
               const total = res.total;
               // 合并新数据到列表中
			   
               this.list = [...this.list, ...data];
               console.log('Updated list:', this.list);
               
               // 更新状态
               this.status = data.length < this.pageSize ? 'nomore' : 'loadmore';
			   this.total = total; // 更新总条数
			    uni.hideToast();
             }).catch(err => {
               console.error('Error:', err);
               this.status = 'loadmore'; // 请求失败恢复状态
             });
           }, 300); // 延迟1秒
    },
	 // 下拉刷新
	        onPullDownRefresh() {
				  this.current = 1; // 重置为第一页
				  this.list = []; // 清空当前列表数据
				  this.findData(); // 请求第一页数据
				  uni.stopPullDownRefresh(); // 停止下拉刷新

	        },
  //上拉加载
    onReachBottom() {
		console.log('Reached bottom. Status:', this.status);
      if (this.status === 'loading' || this.status === 'nomore') return;
      this.status = 'loading';
      this.current++; // 增加当前页码
      this.findData();
    },
  },

  onLoad() {
  	this.findData()
  }
};
</script>

特别注意 

当我们想要实现下拉刷新时, 就需要在 pages.json 找到该页面,然后添加上该属性。然后利用生命周期函数onPullDownRefresh 进行操作就可以了 很简单

"enablePullDownRefresh": true,

css(这里我有些分不清了 所以把整个页面的css都v过来了 注意甄别)

<style lang="scss" scoped>
.container_teacher {
  display: flex;
  flex-direction: column;

  background-color: #ffffff;
  padding: 10px;
    overflow: hidden; /* 确保 container_teacher 不滚动 */
}

.search-bar {
  width: 100%;
  height: 100rpx;
  margin-top: 2%;
}

.search-bar-box {
  display: flex;
  margin: 0 auto;
  width: 620rpx;
  height: 74rpx;
  border: 5rpx solid #00a8cc;
  border-radius: 50rpx;
}

.search-span {
  width: 100rpx;
  height: 56rpx;
  margin-top: 6rpx;
  margin-left: 30rpx;
}

.search-text {
  width: 100%;
  margin-top: 10rpx;
  margin-left: 20rpx;
  font-size: 30rpx;
  color: #7f7f81;
}

.search-btn {
  background-color: #00a8cc; /* Green */
  color: white;
  text-align: center;
  display: inline-block;
  font-size: 35rpx;
  width: 240rpx;
  height: 70rpx;
  line-height: 65rpx;
  border-radius: 30rpx;
  letter-spacing: 3rpx;
}

.top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  padding: 10px;
}

.topItem {
  background-color: #ffffff;
  // border: 1px solid #dddddd;
  border-radius: 5px;
  padding: 10px;
  width: 24%;
  text-align: center;
  margin-bottom: 10px;
  position: relative;
}

.topItem image {
  position: absolute;
  right: 3px;
  top: 50%;
  transform: translateY(-50%);
}

.wrap {
  flex: 1;
  overflow-y: auto;
  padding-bottom: 10px; /* 确保内容不会贴在底部 */
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

.item {

  margin-top: 10px;
  width: 97%;
  padding: 15px;
  box-shadow: 0px 0px 6px #ccc;
  border-radius: 5px;
  background-color: #ffffff;
}

.main_toalbox {
  display: flex;
  flex-direction: column;
  cursor: pointer;
}

.main-box {
  display: flex;
}

.main-box_1 {
  flex: 1;
  display: flex;
  align-items: center;
}

.main-box_2 {
  flex: 4;
}

.main-box_2 .li_1 {
  font-size: 16px;
  font-weight: bold;
}

.main-box_2 .li_2 {
  color: #666666;
}

.main-box_2 .li_3 {
  color: #999999;
}

.main-box_2 .li_4 {
  font-size: 14px;
  color: #fa7409;
}

.u-border-bottom {
  border-bottom: 1px solid #dddddd;
}

.isOver {
  font-size: 20px;
  margin: 0 auto;
  width: 70%;
  padding: 5px;
}

.ellipsis {
  max-width: 80px; /* 根据需要调整宽度 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.area-label {
  background-color: #eff0fe; /* 设置背景颜色 */
  color:#8a8ba5;
  padding: 3px 7px;
  margin-right: 3px;
  border-radius: 5px;
  font-size: 12px;
  display: inline-block;
}

.subject-label {
  background-color: #dbfcfb; /* 这里设置统一的背景颜色 */
  padding: 3px;
  margin-right: 3px;
  border-radius: 5px; /* 圆角 */
  display: inline-block;
  font-size: 12px;
  color:#66d7b2;
}
</style>

完整版本(只需要改一下接口和属性名 其他的全部复制粘贴 就可以使用 )

<template>
	<view>
		<view class="wrap">
			<view class="item u-border-bottom" v-for="(item, index) in list" :key="index">
				<view class="main_toalbox" @click="toTeacherResume(item.teacherId)">
					<view class="main-box">
						<view class="main-box_1">
							<ul>
								<li>
									<u-avatar :show-sex="true" :sex-icon="getSexIcon(item.teacherGender)"
										:src="`${BASE_URL}${item.teacherAvatar}`"></u-avatar>
								</li>
								<li style="font-size: 12px;color: #999999;">最近登录</li>
								<li style="padding-left: 10px;font-size: 12px;color: #999999;">今天</li>
							</ul>
						</view>
						<view class="main-box_2">
							<ul>
								<li class="li_1">
									<span>{{ getTeacherLabel(item.teacherName)}}</span>
								</li>
								<li class="li_2">
									<span style="
		                      display: inline-block;
		                      margin-left: 0px;
		                      margin-top: 8px;
		                      width: 25px;
		                      margin-right: 5px;
		                      text-align: center;
		                      border-radius: 5px;
		                      background-color: #6e7ac2;
		                      color: #ffffff;">{{ item.teacherGender }}</span>
									<span style="
		                      width: 80px;
		                      display: inline-block;
		                      margin-right: 7px;
		                      text-align: center;
		                      border-radius: 5px;
		                      background-color: #6e7ac2;
		                      color: #ffffff;
		                      margin-top: 8px;
		                    ">{{ item.starRating }}</span>
									<span style="
		                      color: #fa7409;
		                      background-color: #ffffff;
		                      border: 1px solid #fa7409;
		                      margin-top: 8px;
		                      border-radius: 5px;
							  padding-left: 5px;
							  padding-right: 5px;">{{ item.university }}</span>
								</li>
								<li class="li_3" style="margin-top: 8px;">
									<span style="color: black;">家教区域:</span>
									<span v-for="(area,index) in splitAreas(item.teachingArea)" :key="index"
										class="area-label">
										{{area}}
									</span>
									<span v-if="item.teachingArea.split(',').length > 3"></span>
								</li>
								<li class="li_4" style="margin-top: 8px;">
									<span style="color: black;">家教科目:</span>
									<span v-for="(subject, index) in displayedSubjects(item.tutoringSubjects)"
										:key="index" class="subject-label">
										{{ subject }}
									</span>
								</li>
							</ul>
						</view>
					</view>
				</view>
			</view>
			<u-loadmore :status="status" style="margin-top: 20px;" />
		</view>
	</view>
</template>

<script>
	import {
		getTutorList
	} from "@/api/getTutorList.js"; //引入获取数据的接口
	import {
		BASE_URL
	} from "@/static/js/data.js"; //方便修改服务器地址
	export default {
		data() {
			return {
				status: 'loadmore', // 组件状态,指的是加载更多
				list: [], //存放数据
				current: 1, //当前页
				pageSize: 5, //页面大小
				showTotal: true, //是否显示“下拉加载更多~”
				BASE_URL, //方便修改服务器地址 同一写到一个data.js中
				selectedGender: '',
				selectedGenderLabel: '性别',
				selectedStar: '',
				selectedStarLabel: '星级',
				selectedCity: '',
				selectedCityLabel: '城市',
				selectedSubject: '',
				selectedSubjectLabel: '科目',

			};
		},
		methods: {
			getSexIcon(teacherGender){
					return  teacherGender ==='女'? 'woman' : 'man'
				},
			splitAreas(teachingArea) {
			    // 确保传入的是一个字符串,否则返回空数组
			    if (!teachingArea || typeof teachingArea !== 'string') return [];
			
			    // 将字符串按逗号分割为数组
			    const areaArray = teachingArea.split(',');
			
			    // 如果区域数量超过3个,展示前三个并加上'...'
			    if (areaArray.length > 3) {
			      return areaArray.slice(0, 3);
			    }
			
			    // 否则直接展示全部区域
			    return areaArray;
			  },
			 getTeacherLabel(name) {
			   if (name && name.length > 0) {
			     // 取姓名的第一个字并加上"教员"
			     return name.charAt(0) + '教员';
			   }
			   return '教员'; // 如果名字为空,默认显示"教员"
			 },
			 displayedSubjects(subjects) {
			   // 将字符串按逗号分割为数组
			   const subjectArray = subjects.split(',');
			   
			   // 如果科目数量超过3个,展示前三个并加上'...'
			   if (subjectArray.length > 3) {
			     return [...subjectArray.slice(0, 3)];
			   }
			   // 否则直接展示全部科目
			   return subjectArray;
			 },
			//因为头像组件的值是man/woman 但是我接收到数据是男/女 所以这里要调整一下
			getSexIcon(teacherGender) {
				return teacherGender === '女' ? 'woman' : 'man'
			},
			search() {
				this.status = 'loadmore';
				this.list = [];
				this.current = 1;
				this.findData();
			},
			//获取数据
			findData() {
				//当我查找到具体内容后,我想返回全部内容时,这里是用来返回全部 
				const tutoringSubjects = this.selectedSubject === '科目' ? '' : this.selectedSubject;
				const tutoringStar = this.selectedStar === '不限' ? '' : this.selectedStar;
				const tutoringCity = this.selectedCity === '全部' ? '' : this.selectedCity;
				const tutoringGender = this.selectedGender === '不限' ? '' : this.selectedGender;
				//根据不同接口,写上需要传输的参数 
				const params = {
					current: this.current,
					pageSize: this.pageSize,
					teaching_area: tutoringCity,
					teacher_gender: tutoringGender,
					star_rating: tutoringStar,
					current_address: '',
					tutoring_subjects: tutoringSubjects
				};
				console.log('Params:', params); // 打印筛选条件
				uni.showToast({
					title: '加载中',
					icon: 'loading',
					duration: 1000 // 1秒后自动消失
				});
				setTimeout(() => {
					getTutorList(params).then(res => {
						console.log('Response:', res);
						const data = res.tutors || [];
						const total = res.total;
						// 合并新数据到列表中

						this.list = [...this.list, ...data];
						console.log('Updated list:', this.list);

						// 更新状态
						this.status = data.length < this.pageSize ? 'nomore' : 'loadmore';
						this.total = total; // 更新总条数
						uni.hideToast();
					}).catch(err => {
						console.error('Error:', err);
						this.status = 'loadmore'; // 请求失败恢复状态
					});
				}, 300); // 延迟1秒
			},
			// 下拉刷新
			onPullDownRefresh() {
				this.current = 1; // 重置为第一页
				this.list = []; // 清空当前列表数据
				this.findData(); // 请求第一页数据
				uni.stopPullDownRefresh(); // 停止下拉刷新

			},
			//上拉加载
			onReachBottom() {
				console.log('Reached bottom. Status:', this.status);
				if (this.status === 'loading' || this.status === 'nomore') return;
				this.status = 'loading';
				this.current++; // 增加当前页码
				this.findData();
			},
		},

		onLoad() {
			this.findData()
		}
	};
</script>

<style lang="scss" scoped>
	.container_teacher {
		display: flex;
		flex-direction: column;

		background-color: #ffffff;
		padding: 10px;
		overflow: hidden;
		/* 确保 container_teacher 不滚动 */
	}

	.search-bar {
		width: 100%;
		height: 100rpx;
		margin-top: 2%;
	}

	.search-bar-box {
		display: flex;
		margin: 0 auto;
		width: 620rpx;
		height: 74rpx;
		border: 5rpx solid #00a8cc;
		border-radius: 50rpx;
	}

	.search-span {
		width: 100rpx;
		height: 56rpx;
		margin-top: 6rpx;
		margin-left: 30rpx;
	}

	.search-text {
		width: 100%;
		margin-top: 10rpx;
		margin-left: 20rpx;
		font-size: 30rpx;
		color: #7f7f81;
	}

	.search-btn {
		background-color: #00a8cc;
		/* Green */
		color: white;
		text-align: center;
		display: inline-block;
		font-size: 35rpx;
		width: 240rpx;
		height: 70rpx;
		line-height: 65rpx;
		border-radius: 30rpx;
		letter-spacing: 3rpx;
	}

	.top {
		display: flex;
		flex-wrap: wrap;
		justify-content: space-around;
		padding: 10px;
	}

	.topItem {
		background-color: #ffffff;
		// border: 1px solid #dddddd;
		border-radius: 5px;
		padding: 10px;
		width: 24%;
		text-align: center;
		margin-bottom: 10px;
		position: relative;
	}

	.topItem image {
		position: absolute;
		right: 3px;
		top: 50%;
		transform: translateY(-50%);
	}

	.wrap {
		flex: 1;
		overflow-y: auto;
		padding-bottom: 10px;
		/* 确保内容不会贴在底部 */
		display: flex;
		justify-content: center;
		align-items: center;
		flex-direction: column;
	}

	.item {

		margin-top: 10px;
		width: 97%;
		padding: 15px;
		box-shadow: 0px 0px 6px #ccc;
		border-radius: 5px;
		background-color: #ffffff;
	}

	.main_toalbox {
		display: flex;
		flex-direction: column;
		cursor: pointer;
	}

	.main-box {
		display: flex;
	}

	.main-box_1 {
		flex: 1;
		display: flex;
		align-items: center;
	}

	.main-box_2 {
		flex: 4;
	}

	.main-box_2 .li_1 {
		font-size: 16px;
		font-weight: bold;
	}

	.main-box_2 .li_2 {
		color: #666666;
	}

	.main-box_2 .li_3 {
		color: #999999;
	}

	.main-box_2 .li_4 {
		font-size: 14px;
		color: #fa7409;
	}

	.u-border-bottom {
		border-bottom: 1px solid #dddddd;
	}

	.isOver {
		font-size: 20px;
		margin: 0 auto;
		width: 70%;
		padding: 5px;
	}

	.ellipsis {
		max-width: 80px;
		/* 根据需要调整宽度 */
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.area-label {
		background-color: #eff0fe;
		/* 设置背景颜色 */
		color: #8a8ba5;
		padding: 3px 7px;
		margin-right: 3px;
		border-radius: 5px;
		font-size: 12px;
		display: inline-block;
	}

	.subject-label {
		background-color: #dbfcfb;
		/* 这里设置统一的背景颜色 */
		padding: 3px;
		margin-right: 3px;
		border-radius: 5px;
		/* 圆角 */
		display: inline-block;
		font-size: 12px;
		color: #66d7b2;
	}
</style>

uniapp中,可以使用uni的内置组件来实现下拉刷新和上划加载更多的功能。 下拉刷新是指在页面顶部下拉时触发的刷新操作。可以通过在页面的<template>中使用<uni-scroll-view>组件,并设置refresher属性为true,然后在<uni-scroll-view>组件的bindrefresh事件中添加下拉刷新的逻辑代码。具体实现如下: <template> <view> <uni-scroll-view refresher="{{ true }}" bindrefresh="onRefresh"> <view>下拉刷新内容</view> </uni-scroll-view> </view> </template> <script> export default { methods: { onRefresh() { // 下拉刷新逻辑代码 // 例如请求数据,更新页面内容等操作 // 刷新完成后,调用uni.stopPullDownRefresh()方法停止下拉刷新的动画 } } } </script> 上划加载更多是指在页面底部上划时触发的加载更多操作。可以通过在页面的<template>中使用<uni-scroll-view>组件,并设置scroll-y属性为true,然后在<uni-scroll-view>组件的bindscrolltolower事件中添加上划加载更多的逻辑代码。具体实现如下: <template> <view> <uni-scroll-view scroll-y="{{ true }}" bindscrolltolower="onLoadMore"> <view>上划加载更多内容</view> </uni-scroll-view> </view> </template> <script> export default { methods: { onLoadMore() { // 上划加载更多逻辑代码 // 例如请求下一页数据,追加到页面内容中等操作 } } } </script> 通过以上方式,可以在uniapp中实现下拉刷新和上划加载更多的功能,提升用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值