Vue封装mescroll组件
写在前面搜罗全网,终于找到一个好用的Vue滑动组件,包括上拉加载,下拉刷新等一大堆好用的方法,他就是mescroll组件,由于很多个页面都需要用到mescroll组件,所以自己把他封装成了一个组件,方便自己使用mescroll组件<template><div class="mescroll-wrap"><mescroll ref="mescrol...
·
写在前面
搜罗全网,终于找到一个好用的Vue滑动组件,包括上拉加载,下拉刷新等一大堆好用的方法,他就是mescroll组件,由于很多个页面都需要用到mescroll组件,所以自己把他封装成了一个组件,方便自己使用
mescroll组件
<template>
<div class="mescroll-wrap">
<mescroll ref="mescroll" :down="down" :up="up" @init="init">
<!-- 列表 -->
<slot></slot>
</mescroll>
</div>
</template>
<script>
import mescroll from 'mescroll.js/mescroll.vue'
export default {
props: {
// 无数据提示 非必需
emptyText: {
type: String,
default () {
return '暂无相关数据'
}
},
// 显示noMore条数据就显示“没有更多数据了” 非必需
noMore: {
type: Number,
default () {
return 10
}
},
// 每页多少条
pageSize: {
type: Number,
default () {
return 10
}
},
// 父ID 必需
warpId: {
type: String,
default () {
return null
}
},
// 下拉刷新的位置 非必需
downRefresh: {
type: String,
default () {
return null
}
},
// 回顶部时间 非必需
topTime: {
type: Number,
default () {
return 4
}
},
downText: {
type: Object,
default () {
return {
textInOffset: "<i class='iconfont icon-shang-copy'></i><span>下拉刷新</span>",
textOutOffset: "<i class='iconfont icon-shang-copy-copy'></i><span>松开刷新</span>",
textLoading: '加载中...'
}
}
},
btntext: {
type: String,
default () {
return null
}
}
},
data () {
return {
mescroll: null,
down: {
offset: 50,
auto: false,
hardwareClass: 'mescroll-hardware',
resetClass: 'mescroll-downwarp-reset',
warpClass: 'mescroll-downwarp',
mustToTop: true,
warpId: this.downRefresh,
callback: this.downCallback,
...this.downText, // 下拉刷新文字
htmlContent: `<div class="downwarp-onload">
<p class="downwarp-progress"></p>
<p class="downwarp-tip">加载中…</p>
</div`
},
up: {
offset: 0,
hardwareClass: 'mescroll-hardware',
warpClass: 'mescroll-upwarp',
isBounce: true,
callback: this.upCallback,
htmlNodata: "<p class='upwarp-nodata'>没有更多数据啦…</p>",
toTop: {
warpId: this.warpId, // mescroll
src: require('./image/火箭.png'), // 回顶图标路径
offset: 400, // 滑动多少距离才显示回顶图标
duration: this.topTime, // 页面回顶时间
warpClass: 'mescroll-totop', // 返回顶部按钮class名
showClass: 'mescroll-fade-in', // 返回顶部按钮进入class名
hideClass: 'mescroll-fade-out', // 返回顶部按钮隐藏class名
btnClick: this.btnClick
},
htmlLoading: '<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">加载中…</p>',
lazyLoad: {
use: true, // 开启懒加载
attr: 'imgurl', // 网络图的自定义属性名
showClass: '', // 懒加载图片展示方式
// mescroll-lazy-in
delay: 50, // 延时时间
offset: 50 // 滑动时离底部多少距离才开始展示图片
},
empty: {
// 列表第一页无任何数据时,显示的空提示布局; 需配置warpId才显示
warpId: this.warpId, // 父布局的id (1.3.5版本支持传入dom元素)
icon: require('./image/no.png'), // 图标,默认null,支持网络图
tip: this.emptyText, // 提示
btntext: this.btntext,
btnClick: this.btntext ? this.btnClick : null
},
noMoreSize: this.noMore,
onScroll: this.onScroll,
page: {
size: this.pageSize
}
}
}
},
components: {
mescroll
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
init (mescroll) {
this.mescroll = mescroll
},
downCallback () {
if (this.warpId !== 'chat-wrap') {
this.$parent.page.page = 1
}
this.$parent.page.pageSize = 10
// 下拉刷新不至于太快
let timer = setTimeout(() => {
this.$emit('getData')
clearTimeout(timer)
}, 500)
},
// 上拉回调
upCallback () {
// if (this.$parent.page.page === 2) return
this.$emit('getData')
},
// 获取记录的滚动位置
getTop () {
this.$refs.mescroll && this.$refs.mescroll.beforeRouteEnter()
},
// 记录位置
setTop () {
this.$refs.mescroll && this.$refs.mescroll.beforeRouteLeave()
},
onScroll (mescroll, y, isUp) {
this.$parent.y = y
this.y = y
this.isUp = isUp
this.$emit('onScroll', y, isUp)
},
// 点击图片回到顶部方法,加计时器是为了过渡顺滑
btnClick () {
this.isUp = false
let timer = setInterval(() => {
let ispeed = Math.floor(-this.y / (this.topTime + 1))
this.$refs.mescroll.$refs.mescroll.scrollTop = this.y + ispeed
if (this.y === 0 || this.isUp) {
clearInterval(timer)
}
}, 16)
return true
}
}
}
</script>
<style lang="less">
// iconfont的上箭头和下箭头
@import '//at.alicdn.com/t/font_1190508_vm3jx9rejm.css';
// 无数据按钮
.mescroll-empty .empty-btn {
top: 26/75rem;
min-width: 40%;
max-width: 50%;
margin: 20/75rem auto;
padding: 24/75rem 20/75rem;
border: 0;
border-radius: 8/75rem;
background-color: #f95644;
color: #fff;
position: relative;
z-index: 10;
font-size: 28/75rem;
}
// 没有更多数据啦
.upwarp-nodata{
padding: 16px 0;
}
// 下拉刷新上下距离
.downwarp-onload{
margin-top: -6px;
}
// 上拉加载loading上下距离
.mescroll-upwarp, .mescroll-hardware {
padding: 0 0;
}
.downwarp-content{
padding: 0!important;
}
// 下拉刷新文字
.downwarp-tip{
margin-left: 2px!important;
.iconfont{
font-size: 38/75rem;
color: rgb(158, 158, 158);
margin-right: @12px;
vertical-align: middle;
}
}
.downwarp-progress{
display: none!important;
&.mescroll-rotate{
display: inline-block!important;
background-size: contain;
animation: progressRotate .8s steps(12, end) infinite;
}
}
.upwarp-progress{
background-size: contain;
animation: progressRotate .8s steps(12, end) infinite;
}
.mescroll-downwarp .downwarp-progress,
.mescroll-upwarp .upwarp-progress{
width: 24px;
height: 24px;
border: none;
margin: auto;
background-size: contain;
background-image: url('./image/loading.svg');
}
.upwarp-progress{
margin: 12px 0 !important;
}
@keyframes progressRotate {
0% {
-webkit-transform: rotate3d(0, 0, 1, 0deg);
transform: rotate3d(0, 0, 1, 0deg);
}
100% {
-webkit-transform: rotate3d(0, 0, 1, 360deg);
transform: rotate3d(0, 0, 1, 360deg);
}
}
.mescroll-wrap{
.mescroll-sticky{
position: sticky;
top: -1px;
z-index: 5;
background: #fff;
}
.mescroll-totop:active{
opacity: 0.7;
}
.mescroll-fade-in {
transition: all linear .3s;
}
.mescroll-fade-out {
transform: translateY(40px);
transition: all linear .3s;
opacity: 0;
}
.mescroll {
position: absolute;
z-index: 2;
height: auto;
}
}
</style>
调用方法
<template>
<div id='parentId'>
<mescroll
ref="mescroll"
@getData='getData()'
warpId='parentId'
emptyText='空数据提示' >
<!-- 内容 -->
</mescroll>
</div>
</template>
<script>
import mescroll from '@/base/mescroll/mescroll'
export default {
data () {
return {
list: [],
// 定义page
page: {
page: 1,
pageSize: 10
}
}
},
beforeRouteEnter (to, from, next) {
next(vm => {
vm.$refs.mescroll.getTop() // 返回页面保留原位置,路由需加keep-alive
})
},
beforeRouteLeave (to, from, next) {
this.$refs.mescroll.setTop() // 离开页面记住位置,路由需加keep-alive
next()
},
created () {
},
methods: {
getData () {
if (this.page.page === 1) {
this.list = []
}
getActivity().then((res) => {
// 请求接口,返回的数据
this.list = [...this.list, ...res.data.list]
this.page.page += 1
// 传递参数,本页的数据、是否有下一页
this.$nextTick(() => {
// 后台返回hasNextPage告知是否有下一页,或者前端这边自己判断
this.$refs.mescroll.mescroll.endSuccess(res.data.list.length, res.data.hasNextPage)
})
})
}
}
}
</script>
<style lang="less" scoped>
@import '../../../../common/less/pixel.less';
/deep/.mescroll {
position: absolute;
top: 176/75rem;
bottom: 98px/75rem;
z-index: 2;
height: auto;
}
/deep/.mescroll-empty {
padding-top: 450/75rem;
}
</style>
有问题,请指正,谢谢?
更多推荐
已为社区贡献8条内容
所有评论(0)