一、上拉刷新和加载
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <title>Page Title</title> <meta name='viewport' content='width=device-width, initial-scale=1'> <!-- 引入样式文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.4/lib/index.css"> <!-- 引入 Vue 和 Vant 的 JS 文件 --> <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vant@2.4/lib/vant.min.js"></script> </head> <body> </body> <template> <div id="video_wrap"> <div class="video_tab"> <van-pull-refresh v-model="isLoading" @refresh="onRefresh"> <van-list v-model="loading" :finished="finished" @load="onLoad"> </van-list> <div class="no_more" v-show="finished">---到底了哦---.</div> </van-pull-refresh> </div> </div> </template> <script> let vm = new Vue({ el: "#app", data() { return { videoList: [],//用于存放加载的数据 loading: false,//控制上拉加载的加载动画 finished: false,//控制在页面往下移动到底部时是否调用接口获取数据 isLoading: false,//控制下拉刷新的加载动画 pageNum: 1, // 页数 offset: 0, // 下次加载起始页 totalPage: 0 // 总页数 } }, template: "#video_wrap"//通过该属性可以将自定义的template属性中的内容全部替换app的内容,并且会覆盖里面原有的内容,并且在查看dom结构时没有template标签 , methods: { async init() { let that = this; let params = { offset: (that.pageNum - 1) * 8 }; let res = await axios.get(this.$HOST + '/open/health/message/center/app/videoList', params); that.videoList = res.result.videosAll.data; // 第一页内容 that.pageNum = res.result.videosAll.page; // 当前显示页 that.totalPage = Math.ceil(res.result.videosAll.total / res.result.videosAll.limit); // 总页数 if (res.result.videosAll.total < 10) { that.finished = true; // 加载结束 that.isLoading = false; that.loading = false; return false; } }, async concatData() { let that = this; that.pageNum += 1; // 数据全部加载完成 let params = { offset: (that.pageNum - 1) * 8 }; let res = await this.$http.get(this.$HOST + '/open/health/message/center/app/videoList', params); if (res.result.videosAll.total < 10) { that.finished = true; // 加载结束 that.isLoading = false; that.loading = false; return false; } that.videoList = that.videoList.concat(res.result.videosAll.data); this.loading = false; if (this.pageNum >= this.totalPage) { that.finished = true; // 加载结束 that.isLoading = false; that.loading = false; } }, onRefresh() { setTimeout(() => { this.$toast({ message: '刷新成功', position: 'bottom' }); this.isLoading = false; this.pageNum = 1; this.loading = false; this.finished = false; this.isLoading = false; this.init(); }, 500); }, onLoad() { // 异步更新数据 setTimeout(() => { this.concatData(); }, 500); } }, async created() { this.init(); } }); </script> </html>
参考请求方法。如果不想让按钮在一开始的时候存在,而是在滚动了一定的距离的时候再出现,那设置 一个滚动条的监听就搞定啦,
mounted() {
window.addEventListener('scroll', this.handleScroll, true)
},
//methods中定义事件
handleScroll(env){
let scrollTop = document.getElementsByClassName('equi_container')[0].scrollTop
if(scrollTop > 100){
this.flag_scroll = true
}else {
this.flag_scroll = false
}
},
案例例子
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <title>Page Title</title> <meta name='viewport' content='width=device-width, initial-scale=1'> <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> <!-- 引入样式文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.4/lib/index.css"> <!-- 引入 Vue 和 Vant 的 JS 文件 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vant@2.4/lib/vant.min.js"></script> <style type="text/css"> * { padding: 0; margin: 0; } html, body { overflow: hidden; } /*禁用接管浏览器滚动条*/ .list{ margin-top:46px; overflow:auto; } .list-item{ text-align:center; } </style> </head> <body> <div id="app"> </div> <!--此处template标签必须在vue绑定的元素外面定义,并且在页面中不显示下面的template标签中的内容--> <template id="first"> <div> <van-nav-bar fixed title="数据列表" right-text="退出登录"></van-nav-bar> <div class="list" id="list"> <van-pull-refresh v-model="isLoading" @refresh="onRefresh"> <van-list v-model="loading" :finished="finished" @load="onLoad" :offset="10"> <div class="list-item"> <van-cell v-for="(item,key) in list" :key="key" :title="item + '' " /> </div> </van-list> </van-pull-refresh> </div> </div> </template> <script> let vm = new Vue({ el: "#app", data: { list: [], loading: false, //是否处于加载状态 finished: false, //是否已加载完所有数据 isLoading: false, //是否处于下拉刷新状态 }, template: "#first"//通过该属性可以将自定义的template属性中的内容全部替换app的内容,并且会覆盖里面原有的内容,并且在查看dom结构时没有template标签 , methods: { onLoad() { //上拉加载 setTimeout(() => { for (let i = 0; i < 15; i++) { this.list.push(this.list.length + 1); } this.loading = false; if (this.list.length >= 60) { this.finished = true; } }, 500); }, onRefresh() { //下拉刷新 setTimeout(() => { this.finished = false; this.isLoading = false; this.list = [] this.onLoad() }, 500); } }, mounted() { let winHeight = document.documentElement.clientHeight; //浏览器视口大小 document.getElementById("list").style.height = (winHeight - 50) + "px" //调整框高度 } }); </script> </body> </html>
二、配合tabs模板
如图所示:
代码如下:
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <title>Page Title</title> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"> <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> <!-- 引入样式文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.4/lib/index.css"> <!-- 引入 Vue 和 Vant 的 JS 文件 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vant@2.4/lib/vant.min.js"></script> <style type="text/css"> * { padding: 0; margin: 0; } html, body { overflow: hidden; /*1、禁用body滚动条*/ } .list { margin-top: 46px; overflow: auto; -webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: auto; /*2、设置局部容器的内容超出可以滚动并显示滚动条 注意:容器内部item 必须设置宽和高*/ } /*内部元素设置可以滚动*/ .list-item { text-align: center; } </style> </head> <body> <div id="app"> </div> <!--此处template标签必须在vue绑定的元素外面定义,并且在页面中不显示下面的template标签中的内容--> <template id="first"> <div> <van-nav-bar fixed title="数据列表" right-text="退出登录"></van-nav-bar> <van-button type="default" style="position: fixed !important ;right:2rem !important;bottom: 4rem !important;z-index: 99 !important; background-color:rgba(0,0,0,0.1) !important" class="backTop" sticky @click="backTop" v-show="flag_scroll"> <van-icon name="arrow-up" size="20" /> </van-button> <div class="list" id="list"> <van-tabs v-model="active" sticky @click="changeAct"> <van-tab v-for="(item,ind) in navtitle" :title="item" :key="ind"> <van-pull-refresh v-model="isLoading" @refresh="onRefresh"> <van-list v-model="loading" :finished="finished" finished-text="没有更多了" :immediate-check="false" @load="onLoad(page,keyword,orderColumn)" :offset='0'> <!--<IndexTemp v-for="(item,i) in goodList" :good="item" :key="i"></IndexTemp>--> <!--必须指定高度,否则会影响监听底部,会导致出现不显示滚动条--> <!--<van-cell style="height: 200px;" v-for="(item,key) in list" :key="key" :title="item + '' " />--> <template v-for="(item,key) in list"> <!--这种宽度必须指定,否则触发这两次--> <img height="200px" width="100%" src="https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1208538952,1443328523&fm=26&gp=0.jpg" /> </template> </van-list> </van-pull-refresh> </van-tab> </van-tabs> </div> </div> </template> <script> let vm = new Vue({ el: "#app", data: { active: 0, navtitle: ["默认", "价格", "上新"], orderTypeCut: "desc",// page: 0, //当前页 keyword: "", //关键字查询 orderColumn: "", // list: [], //数据 loading: false, //是否处于加载状态 finished: false, //是否已加载完所有数据 isLoading: false, //是否处于下拉刷新状态 flag_scroll: false,//是否显示返回顶部按钮 }, template: "#first"//通过该属性可以将自定义的template属性中的内容全部替换app的内容,并且会覆盖里面原有的内容,并且在查看dom结构时没有template标签 , methods: { //切换tab changeAct(index, title) { this.active = index; this.orderColumn = title == '价格' ? 'price' : title == '上新' ? 'time' : 'default'; if (this.orderColumn == 'price') { this.orderTypeCut = !this.orderTypeCut; } this.orderType = this.orderTypeCut ? 'desc' : 'asc'; this.page = 1; //初始化1 this.list = []; //初始化数据 this.loading = true; //设置加载中状态 this.finished = false; //设置为未加载所有数据状态 if (this.loading) { this.onLoad(this.page, this.keyword, this.orderColumn); } }, onLoad(page, keyword, orderColumn) { //上拉加载 setTimeout(() => { for (let i = 0; i < 15; i++) { this.list.push(this.list.length + 1); } this.loading = false; if (this.list.length >= 60) { this.finished = true; } }, 500); }, onRefresh() { //下拉刷新 setTimeout(() => { this.finished = false; this.isLoading = false; this.list = [] this.onLoad() }, 500); }, backTop() //返回顶部 { //document.getElementsByClassName('list')[0].scrollTop=0; $('.list').animate({ scrollTop: 0 }, 500); }, handleScroll(env) { let scrollTop = document.getElementsByClassName('list')[0].scrollTop; console.log("滚动位置:" + scrollTop); if (scrollTop > 100) { this.flag_scroll = true } else { this.flag_scroll = false } }, }, created() { }, mounted() { this.onLoad() //创建的时候触发 let winHeight = document.documentElement.clientHeight; //浏览器视口大小 document.getElementById("list").style.height = (winHeight - 44) + "px" //调整框高度 //滚动条的监听显示回返顶部按钮 获取并存储当前 scrollTop window.addEventListener('scroll', this.handleScroll, true) }, destroyed() { window.removeEventListener('scroll', this.handleScroll, true) }, }); </script> </body> </html>
发现的问题:超出了2px
然后查找原因
问题是: 会出现两个滚动条,这个是超出屏幕的滚动条,一个是你写的超出.list的滚动条
发现受阻比较小,但是切换后,还是一个新的下拉,每次触发下拉请求,这是很重要的(只不过下拉加载触感太低) ,切换都是新的加载,没法保留,这个限制
我当时为了解决多个上拉,而且为了固定,发现完全不用 用粘性布局,外层放置一个div即可
当时的例子,不推荐自己更改css,应该当时布局好 header 中间 和底部
<template> <div class="page"> <van-row id="header"> <van-col span="24"> <!--NavBar 导航栏fixed 以及z-index--> <van-nav-bar z-index="3" fixed title="标题" left-text="返回" right-text="按钮" left-arrow @click-left="onClickLeft" @click-right="onClickRight" ></van-nav-bar> </van-col> </van-row> <van-row class="content" id="content"> <van-col span="24"> <!--Tab 标签页--> <van-tabs z-index="2" v-model="active" swipeable> <van-tab title="标签 1"> <!--PullRefresh 下拉刷新--> <van-pull-refresh v-model="isLoading1" @refresh="onRefresh1"> <!--<p>刷新次数: {{ count }}</p> --> <!--List 列表 滚动加载--> <van-list v-model="loading1" :finished="finished1" @load="onLoad1" :offset="10"> <div class="list-item"> <template v-for="(item,index) in list1"> <van-cell :key="index">A item{{item}}</van-cell> </template> </div> </van-list> </van-pull-refresh> </van-tab> <van-tab title="标签 2"> <!--PullRefresh 下拉刷新--> <van-pull-refresh v-model="isLoading2" @refresh="onRefresh2"> <!--<p>刷新次数: {{ count }}</p> --> <!--List 列表 滚动加载--> <van-list v-model="loading2" :finished="finished2" @load="onLoad2" :offset="10"> <div class="list-item"> <template v-for="(item,index) in list2"> <van-cell :key="index">B item{{item}}</van-cell> </template> </div> </van-list> </van-pull-refresh> </van-tab> <van-tab title="标签 3">内容 3</van-tab> <van-tab title="标签 4">内容 4</van-tab> </van-tabs> </van-col> </van-row> <van-row class="footer"> <van-col span="24"> <!--Tabbar 标签栏--> <tabbar></tabbar> </van-col> </van-row> </div> </template> <script> import tabbar from "../../components/tabbar.vue"; //引用组件的地址 export default { components: { tabbar: tabbar }, data() { return { active: 0, count1: 0, list1: [], loading1: false, //是否处于加载状态 finished1: false, //是否已加载完所有数据 isLoading1: false, //是否处于下拉刷新状态 count2: 0, list2: [], loading2: false, //是否处于加载状态 finished2: false, //是否已加载完所有数据 isLoading2: false //是否处于下拉刷新状态 }; }, methods: { onClickLeft() { this.$toast("返回"); }, onClickRight() { this.$toast("按钮"); }, //上拉加载 onLoad1() { setTimeout(() => { for (let i = 0; i < 15; i++) { this.list1.push(this.list1.length + 1); } this.loading1 = false; if (this.list1.length >= 60) { this.finished1 = true; } }, 500); }, //下拉刷新 onRefresh1() { setTimeout(() => { this.$toast("刷新成功"); this.isLoading1 = false; this.count++; }, 1000); }, onLoad2() { setTimeout(() => { for (let i = 0; i < 15; i++) { this.list2.push(this.list2.length + 1); } this.loading2 = false; if (this.list2.length >= 60) { this.finished2 = true; } }, 500); }, //下拉刷新 onRefresh2() { setTimeout(() => { this.$toast("刷新成功"); this.isLoading2 = false; this.count++; }, 1000); } }, mounted() { let winHeight = document.documentElement.clientHeight //视口大小 document.getElementById('content').style.height = (winHeight - 100) +'px' //调整上拉加载框高度 } }; </script> <style scoped> .list-item { text-align: center; } .content { margin-top: 46px; } .content .van-col >>> .van-tabs .van-tabs__wrap { position: fixed; width: 100%; top: 44px; box-sizing: border-box; z-index: 2; } .content .van-col >>> .van-tabs .van-tab__pane { margin-top: 44px; } /* 滚动条的问题 */ .content{ overflow: auto; -webkit-overflow-scrolling: touch; } .page { height: auto; } /*.van-tabs { overflow: auto; height: 100%; box-sizing: border-box; -webkit-overflow-scrolling: touch; }*/ </style>
发现多次一举这样的自定义css ,不过这里面放入多个可以解决多个tab数据保留的问题,只不过上拉加载阻力太低,感觉高度是一开始充满的,不是上拉到底部后触发的
注意:
整理
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <title>Page Title</title> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"> <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> <!-- 引入样式文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.4/lib/index.css"> <link rel="stylesheet" href="./app.min.css"> <!-- 引入 Vue 和 Vant 的 JS 文件 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vant@2.4/lib/vant.min.js"></script> <style type="text/css"> * { padding: 0; margin: 0; } html, body { overflow: auto; background-color: #f7f8fa; } /*禁用接管浏览器滚动条*/ .list { /*如果overflow: hidden;设置的则下拉内应该 配合 margin: 0 1rem;否则list宽度100%滚动条会和body重合,会导致出现消失 */ margin-top: 46px; overflow: auto; width: 100%; box-sizing: border-box; } /*内部元素设置可以滚动*/ .list-item { text-align: center; } /*多层*/ .product_list_medium, .product_list_small { overflow: hidden; } /* .product_list_small small_product列表布局*/ /* flex-wrap 属性 flex-wrap: nowrap|wrap|wrap-reverse|initial|inherit; nowrap - 默认, 弹性容器为单行。该情况下弹性子项可能会溢出容器。 wrap - 弹性容器为多行。该情况下弹性子项溢出的部分会被放置到新行,子项内部会发生断行 wrap-reverse -反转 wrap 排列。 */ .product_list_small .product_div { display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; /*指定宽高 h 必须指定,不然内部其他元素会冲开*/ width: auto; /*auto是随内容的高度而撑开的。100%是根据父级元素的高度来决定的*/ height: 8rem; /*布局*/ margin: 1rem; padding: 1rem; /*指定背景*/ background-color: #ffffff; box-shadow: 0 8px 12px #ebedf0; border-radius: 1rem; /*超出隐藏,以防隐藏到外部的布局*/ overflow: hidden; } /*指定图片框固定大小*/ .product_list_small .product_div .pictrue_div { width: 8rem; height: 100%; } /*设置100%,填充图片框*/ .product_list_small .product_div .pictrue_div img { width: 100%; height: 100%; border-radius: 1rem; } .product_list_small .product_div .dis-box { flex: 1; padding: 1rem; /*这里知道高可以指定title=3rem 内容可以设置3rem即可,而我设置title3 底部 auto 自动计算内容也会是3,用了 弹性盒子*/ display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column; } .product_list_small .product_div .dis-box .product_text { height: 3rem; } .product_list_small .product_div .dis-box .product_remark { flex: 1; } .product_list_medium { display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; } /* .product_list_medium medium-list*/ .product_list_medium .product_div { display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column; /*指定宽高 h 必须指定,不然内部其他元素会冲开*/ width: 46%; /*auto是随内容的高度而撑开的。100%是根据父级元素的高度来决定的*/ height: auto; /*布局*/ margin: 4% 2% 0 2%; padding: 0.4rem; /*指定背景*/ background-color: #ffffff; box-shadow: 0 8px 12px #ebedf0; border-radius: 1rem; /*超出隐藏,以防隐藏到外部的布局*/ overflow: hidden; box-sizing: border-box; } .product_list_medium .product_div .dis-box { box-sizing: border-box; flex: 1; padding: 0.2rem; } .product_list_medium .product_div .pictrue_div { box-sizing: border-box; flex: 1; } /*指定图片框固定大小*/ .product_list_medium .product_div .pictrue_div { width: 100%; height: 14rem; } /*设置100%,填充图片框*/ .product_list_medium .product_div .pictrue_div img { width: 100%; height: 100%; border-radius: 1rem; } /**/ .product_list_big { display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; flex-wrap: wrap; } /* .product_list_big medium-list*/ .product_list_big .product_div { display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column; /*指定宽高 h 必须指定,不然内部其他元素会冲开*/ width: 100%; /*auto是随内容的高度而撑开的。100%是根据父级元素的高度来决定的*/ height: auto; /*布局*/ margin: 4% 2% 0 2%; padding: 0.4rem; /*指定背景*/ background-color: #ffffff; box-shadow: 0 8px 12px #ebedf0; border-radius: 1rem; /*超出隐藏,以防隐藏到外部的布局*/ overflow: hidden; box-sizing: border-box; } .product_list_big .product_div .dis-box { box-sizing: border-box; flex: 1; padding: 0.2rem; } .product_list_big .product_div .pictrue_div { box-sizing: border-box; width: 100%; flex: 1; } /*指定图片框固定大小*/ .product_list_big .product_div .pictrue_div { width: 100%; height: 26rem; } /*设置100%,填充图片框*/ .product_list_big .product_div .pictrue_div img { width: 100%; height: 100%; border-radius: 1rem; } </style> </head> <body> <div id="app"> </div> <!--此处template标签必须在vue绑定的元素外面定义,并且在页面中不显示下面的template标签中的内容--> <template id="first"> <div> <van-nav-bar fixed title="数据列表" right-text="退出登录"></van-nav-bar> <van-button type="default" style="position: fixed !important ;right:2rem !important;bottom: 4rem !important;z-index: 99 !important; background-color:rgba(0,0,0,0.1) !important" class="backTop" sticky @click="backTop" v-show="flag_scroll"> <van-icon name="arrow-up" size="20" /> </van-button> <div class="list" id="list"> <van-tabs v-model="active" swipeable sticky @click="changeAct"> <van-tab v-for="(item,ind) in navtitle" :title="item" :key="ind"> <van-pull-refresh v-model="refreshing" @refresh="onRefresh"> <!-- :immediate-check="false" 是否在初始化时立即执行滚动位置检查--> <!-- :offset='0' 滚动条(滚动条)与底部距离小于 offset 时触发load事件--> <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad(page,keyword,orderColumn)" :error.sync="error" error-text="请求失败,点击重新加载" :offset='0'> <!--<IndexTemp v-for="(item,i) in goodList" :good="item" :key="i"></IndexTemp>--> <!--<van-cell v-for="(item,key) in list" :key="key" :title="item + '' "></van-cell>--> <!-- <div class="product_list_small"> <template v-for="(item,key) in list"> <div class="product_div"> <div class="pictrue_div"> <img src="https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1208538952,1443328523&fm=26&gp=0.jpg" /> </div> <div class="dis-box"> <p class="product_text"> 标题 </p> <p class="product_remark"> 商品描述 简介 一些列信息 </p> </div> </div> </template> </div> --> <!-- <div class="product_list_medium"> <template v-for="(item,key) in list"> <div class="product_div"> <div class="pictrue_div"> <img src="https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1208538952,1443328523&fm=26&gp=0.jpg" /> </div> <div class="dis-box"> <p class="product_text"> 标题 </p> <p class="product_remark"> 商品描述 简介 一些列信息 </p> </div> </div> </template> </div> --> <div class="product_list_big"> <template v-for="(item,key) in list"> <div class="product_div"> <div class="pictrue_div"> <img src="https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1208538952,1443328523&fm=26&gp=0.jpg" /> </div> <div class="dis-box"> <p class="product_text"> 标题 </p> <p class="product_remark"> 商品描述 简介 一些列信息 </p> </div> </div> </template> </div> </van-list> </van-pull-refresh> </van-tab> <van-tab> <template #title> <i class="iconfont icon-pailie" data="0"></i> <!--<i class="iconfont icon-viewlist" data="2"></i>--> <!--<i class="iconfont icon-icon-square" data="2"></i>--> </template> </van-tab> </van-tabs> </div> </div> </template> <script> let vm = new Vue({ el: "#app", data: { active: 0, navtitle: ["默认", "价格", "上新"], orderTypeCut: "desc",// page: 0, //当前页 keyword: "", //关键字查询 orderColumn: "", // list: [], //数据 loading: false, //是否处于加载状态 finished: false, //是否已加载完所有数据 refreshing: false, //是否处于下拉刷新状态 error: false, flag_scroll: false,//是否显示返回顶部按钮 }, template: "#first", //通过该属性可以将自定义的template属性中的内容全部替换app的内容,并且会覆盖里面原有的内容,并且在查看dom结构时没有template标签 methods: { //切换tab changeAct(index, title) { this.active = index; this.orderColumn = title == '价格' ? 'price' : title == '上新' ? 'time' : 'default'; if (this.orderColumn == 'price') { this.orderTypeCut = !this.orderTypeCut; } this.orderType = this.orderTypeCut ? 'desc' : 'asc'; this.page = 1; //初始化1 this.list = []; //初始化数据 this.loading = true; //设置加载中状态 this.finished = false; //设置为未加载所有数据状态 if (this.loading) { this.onLoad(this.page, this.keyword, this.orderColumn); } }, onLoad(page, keyword, orderColumn) { //上拉加载 console.log("触发onload事件"); setTimeout(() => { for (let i = 0; i < 15; i++) { this.list.push(this.list.length + 1); } //加载状态结束 this.loading = false; //数据全部加载完成 if (this.list.length >= 60) { this.finished = true; } }, 500); console.log(this.list); }, onRefresh() { //下拉刷新 setTimeout(() => { this.finished = false; this.refreshing = false; this.list = []; this.onLoad(); }, 500); }, backTop() //返回顶部 { //document.getElementsByClassName('list')[0].scrollTop=0; $('#list').animate({ scrollTop: 0 }, 500); }, handleScroll(env) { let scrollTop = document.getElementById("list").scrollTop; console.log("滚动位置:" + scrollTop); if (scrollTop > 100) { this.flag_scroll = true } else { this.flag_scroll = false } }, }, mounted() { let winHeight = document.documentElement.clientHeight; //浏览器视口大小 document.getElementById("list").style.height = (winHeight - 44) + "px" //调整框高度 //滚动条的监听显示回返顶部按钮 获取并存储当前 scrollTop window.addEventListener('scroll', this.handleScroll, true) }, destroyed() { window.removeEventListener('scroll', this.handleScroll, true) }, }); </script> </body> </html>
刷新触发load,单次和频繁的问题都有,而且拉动只能触动内容的部分才可以拉动
<style scoped> .flex { display: -webkit-flex; display: flex; flex-flow: row nowrap; justify-content: space-between; /*左右布局*/ } .item { background-color: #fff; padding: 1rem; width: 100%; box-sizing: border-box; margin-bottom: 0.4rem; } .item_header { margin-bottom: 0.6rem; height: 1.6rem; font-size: 1rem; } .item_header_right { display: inline-block; font-size: 0.9rem; } .item_header_left img { height: 100%; display: inline-block; vertical-align: middle; } .item_header_left span { margin-left: 0.4rem; display: inline-block; vertical-align: middle; } .item_header_right span { display: inline-flex; vertical-align: middle; } .item_center { background-color: #f8f8f8; font-size: 0.9rem; margin-bottom: 0.6rem; min-height: 3rem; padding: 0.4rem; vertical-align: middle; border-radius: 10px; } .item_footer { font-size: 0.8rem; } </style> <template> <div class="page"> <van-row> <van-col span="24"> <!--NavBar 导航栏fixed 以及z-index--> <van-nav-bar z-index="3" title="进件列表"></van-nav-bar> <!--可添加fixed属性--> </van-col> </van-row> <van-row class="center" id="center"> <van-col span="24"> <!--Tab 标签页--> <!--Tab 标签页--> <van-tabs v-model="active" sticky @click="changeAct" swipeable title-active-color="#05A1E7" color="#05A1E7" > <van-tab v-for="(item,ind) in navtitle" :title="item" :key="ind"> <van-pull-refresh v-model="refreshing" loading-text="加载中..." success-text="刷新成功" @refresh="onRefresh" > <van-list style="min-height: calc(100vh - 147px);" v-model="loading" :finished="finished" finished-text="没有更多了" :immediate-check="true" @load="onLoad" :offset="10" > <template v-if="list.length>0"> <!--<IndexTemp v-for="(item,i) in goodList" :good="item" :key="i"></IndexTemp>--> <!--必须指定高度,否则会影响监听底部,会导致出现不显示滚动条--> <template v-for="(item,index) in list"> <!--这种宽度必须指定,否则触发这两次--> <div class="item" :key="index"> <div class="item_header flex"> <div class="item_header_left"> <img src="../../static/image/order-list-icon.png" /> <span>{{item.personname}}</span> </div> <div class="item_header_right"> <span>{{item.status}}</span> <span class="icon"> <van-icon style="vertical-align: middle;" name="arrow"></van-icon> </span> </div> </div> <div class="item_center"> <span> <template v-if="!!item.statusinfo">{{item.statusinfo}}</template> </span> </div> <div class="item_footer">订单编号:2131322222222</div> </div> </template> </template> <template v-else> <div class="default_footer"> <img src="../../static/icon/icon_loan_default.png" alt="暂无" /> <p>暂时没有该栏目信息</p> </div> </template> </van-list> </van-pull-refresh> </van-tab> </van-tabs> </van-col> </van-row> <van-row class="footer_"> <van-col span="24"> <!--Tabbar 标签栏--> </van-col> </van-row> </div> </template> <script> import Vue from "vue"; export default { data() { return { active: 0, orderColumn: "", navtitle: ["全部", "下户", "审批", "签约", "拒绝"], list: [], //数据集 pageNum: 0, //当前页 pageSize: 1, //加载数据大小 loading: false, //加载状态 finished: false, //数据已经加载完 refreshing: false //下拉刷新状态 }; }, watch: { active: function() { var self = this; this.orderColumn = this.navtitle[this.active]; if (Vue.cancel != null) { Vue.cancel("路由切换时取消axios成功!"); } // self.list=[]; this.pageNum = 1; setTimeout(() => { this.LogicListData(res => { if (res.length < self.pageSize) self.finished = true; self.list = res; }); this.refreshing = false; //刷新状态 结束 }, 1000); } }, methods: { //切换tab changeAct(index) { // console.log("切换执行"); this.active = index; }, GetListData(reqInit) { return this.$axios({ url: reqInit, method: "get" // 请求方式 }) .then(res => { // 请求成功 if (res.data && res.data.length > 0) { //console.log(res.data); } return res; }) .catch(error => { console.log(error); }); }, async LogicListData(successCallback) { var self = this; var status = self.orderColumn; var statusSql = ""; switch (status) { case "下户": statusSql = "and (Status='待下户' or Status='已下户')"; break; case "审批": statusSql = "and (Status='待审批' or Status='已审批')"; break; case "签约": statusSql = "and (Status='已签约' or Status='已抵押')"; break; case "拒绝": statusSql = "and Status='已拒绝'"; break; default: break; } self.loginInfo = JSON.parse(sessionStorage.getItem("loginInfo")); var adminName = self.loginInfo.AdminName; var cityid = self.loginInfo.CityId; var where = "CreateUser='" + adminName + "' and cityid=" + cityid; //if (status == "全部") { // statusSql = " and Status <> '已放款'"; //} //如果是渠道代理商 if (self.loginInfo.LimitName == "渠道代理商") { where = "AgentUser='" + adminName + "' and cityid=" + cityid; } var orderByStr = ""; //如果是下户专员 if ( self.loginInfo.LimitName == "下户专员" || self.loginInfo.LimitName == "下户调度专员" ) { statusSql = ""; orderByStr = ",HouseTimeOrder asc"; where = "HouseUser='" + adminName + "' and Status='待下户' and cityid=" + cityid; if (status == "全部") { where = "HouseUser='" + adminName + "' and cityid=" + cityid; } } //初始化信息 var sqlInit = "select ID,PersonName,CreateUser,StatusInfo,LoanNo,Status,HouseTimeOrder,(select Count(1) as Num from Tbl_LoanAssess where LoanID=Tbl_Loan.Id and DealFlag=0) as IsAssess FROM Tbl_Loan where " + where + statusSql + " and IsValid=1 and DealFlag=0 ORDER BY DealTime desc" + orderByStr; // console.log(sqlInit) //统计数量 var sqlTotal = "select count(1) from Tbl_Loan where " + where + statusSql + " and IsValid=1 and DealFlag=0"; var token = 123; //console.log("数据加载:" + sqlInit); var reqInit = "/api.ashx?token=" + token + "&action=data_read&sql=" + sqlInit + "&pagesize=" + self.pageSize + "&pageindex=" + self.pageNum + "&callback=?"; var reqTotal = "/api.ashx?token=" + token + "&action=data_sql&sql=" + sqlTotal + "&pagesize=1&pageindex=1&callback=?"; let res = await this.GetListData(reqInit); if (res.data && res.data.length > 0) { let res2 = await this.GetListData(reqTotal); self.count = JSON.parse(res2.data.result); } successCallback && successCallback(res.data); }, onLoad() { //1、页面加载触发直到沾满整个屏幕此时是频繁的请求 2、触发底部就会频繁触发 console.log("触发onLoad方法"); var self = this; setTimeout(() => { self.pageNum=1; //加载状态结束 self.loading = false; //取消加载 //加载的情况 this.LogicListData(res => { //异步才可以用await,故onload没加async 只能回调处理 if (res.length < self.pageSize) self.finished = true; res.forEach(element => { self.list.push(element); }); }); }, 1000); }, //下拉刷新 onRefresh() { var self = this; this.pageNum = 1; //this.loading = true; //我之前是反过来了 ? 你都没有弄这个 你只管了正常加载的,没有管刷新时候的 主要是控制这个 你再自己研究一下 ,我要搞事了 嗯嗯 我在啊看看 //this.list = []; setTimeout(() => { self.list=[]; //self.onLoad(); /*this.LogicListData(res => { //用onLoad 而不自己写是为了当请求sieze 少的时候,会监听加载满整个屏幕 //异步才可以用await,故onload没加async 只能回调处理 if (res.length < self.pageSize) self.finished = true; self.list = res; });*/ this.refreshing = false; //刷新状态 结束 //this.$toast("刷新成功"); this.loading = true; self.onLoad(); }, 1000); }, //1、解决主动加载数据 loadData() { if (!this.loading) { this.loading = true; this.onLoad(); } } }, mounted() { this.loadData(); //let winHeight = document.documentElement.clientHeight; //视口大小 //document.getElementById("center").style.height = winHeight - 200 + "px"; //调整上拉加载框高度 } }; </script> <style scoped> </style>
具体解决
1、处理了刷新的加载触发load部分
2、影响处理拉动部分的