vue项目之移动端better-scroll的使用
vue项目之移动端better-scroll的使用
封装better-scroll
<template>
<div class="wrapper" ref="wrapper">
<div>
<slot></slot>
</div>
</div>
</template>
<script>
import BScroll from "better-scroll";
export default {
name: "Scroll",
props: {
probeType: {
type: Number,
default: 1,
},
data: {
type: Array,
default: () => {
return [];
},
},
pullUpLoad: {
type: Boolean,
default: false,
},
},
data() {
return {
scroll: {},
};
},
mounted() {
setTimeout(this.__initScroll, 20);
},
methods: {
__initScroll() {
// 1.初始化BScroll对象
if (!this.$refs.wrapper) return;
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: true, // 鼠标点击滚动
// tap: true,
// mouseWheel: true, //鼠标滚轮滚动
pullUpLoad: this.pullUpLoad,
});
// 2.将监听事件回调
this.scroll.on("scroll", (pos) => {
this.$emit("scroll", pos);
});
// 3.监听上拉到底部
this.scroll.on("pullingUp", () => {
console.log("上拉加载");
this.$emit("pullingUp");
});
},
refresh() {
this.scroll && this.scroll.refresh && this.scroll.refresh();
},
finishPullUp() {
this.scroll && this.scroll.finishPullUp && this.scroll.finishPullUp();
},
scrollTo(x, y, time = 500) {
this.scroll && this.scroll.scrollTo && this.scroll.scrollTo(x, y, time);
},
},
watch: {
data() {
setTimeout(this.refresh, 20);
},
},
};
</script>
<style scoped>
</style>
组件使用
<template>
<div class="home">
<baseTitleBar
backgroundColor="#FFF"
:leftEle="leftEle"
:title="title"
titleColor="#000"
></baseTitleBar>
<scroll
class="content"
ref="scroll"
@pullingUp="loadMore"
@scroll="contentScroll"
:data="data"
:pull-up-load="enableLoadMore"
:probe-type="3"
>
<!-- 轮播图 -->
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
<van-swipe-item v-for="(item, idx) in swipeList" :key="idx">
<img :src="item.target" alt="" class="swiper-img" />
</van-swipe-item>
</van-swipe>
<!-- 列表 -->
<div
class="advert-item click w702 bg-fff"
v-for="(item, idx) in data"
:key="idx"
@click="gotoAdvDetail(item.resource_id)"
>
<div class="adv-left">
<div class="fs-30 color-000 flex-center">
<span
class="label fs-24"
:class="{
label: item.rank == '一级屏',
label2: item.rank == '二级屏',
label3: item.rank == '三级屏',
label4: item.rank == '四级屏',
}"
>
{{ item.atlas.category }}
</span>
<span class="adv-title font-bold text-el">
{{ item.resource_info }}
</span>
</div>
<div class="flex-center mt-15">
<div class="tag fs-24 text-el">{{ item.resource_info }}</div>
<div class="line"></div>
</div>
<div class="fs-24 color-333 mt-10 text-el" style="width: 4.9rem">
{{ item.atlas.desc }}
</div>
<div class="mt-24">
<span class="coin fs-28">收藏量{{ item.atlas.like_count }}</span>
<span class="qty fs-20 ml-24">
曝光量{{ item.atlas.favorite_count }}
</span>
</div>
</div>
<div class="adv-right">
<div class="adv-img">
<img :src="item.target" alt="" @load="imageLoad" />
</div>
<div class="dist fs-20" v-if="item.distance">
{{ item.atlas.sender.username }}
</div>
</div>
</div>
</scroll>
<BackTop @click.native="gobackTop" v-show="showBackTop"></BackTop>
</div>
</template>
<script>
import baseTitleBar from "@/components/titleBar/baseTitleBar";
import scroll from "../components/scroll";
import BackTop from "../components/backTop.vue";
import { homeSwipeList, homeGoodsList } from "@/api/home";
export default {
name: "home",
components: { scroll, baseTitleBar, BackTop },
data() {
return {
page: 1,
limit: 10,
data: [],
swipeList: [],
leftEle: {
iconName: "iconback",
color: "#000",
fontSize: ".36rem",
method: this.back,
},
title: "首页",
showBackTop: false,
backTopDistance: 800,
enableLoadMore: true
};
},
methods: {
// 请求轮播数据
async gethomeSwipeList() {
let res = await homeSwipeList();
this.swipeList = res.item;
},
// 请求列表数据
getListData() {
let params = {
// 页数
page: this.page,
limit: this.limit,
};
homeGoodsList(params).then((res) => {
if (res.code == 200) {
if (this.data.length >= res.item.total) {
this.enableLoadMore = false;
return;
}
// this.data = this.data.concat(res.item.resultList);
const homeGoodsList = res.item.resultList;
this.data.push(...homeGoodsList);
this.page += 1;
this.$refs.scroll.finishPullUp();
} else {
console.log("接口出错");
}
});
},
// 加载更多
loadMore() {
this.getListData();
// 用于图片异步加载高度问题刷新
this.$refs.scroll.refresh();
},
// 监听回顶的显示
contentScroll(position) {
// 1.决定tabFixed是否显示
// this.isTabFixed = position.y < -this.tabOffsetTop;
// 2.决定backTop是否显示
this.showBackTop = -position.y > this.backTopDistance;
},
// 回到顶部
backTop() {
this.$refs.scroll.scrollTo(0, 0, 300);
},
// 跳转详情
gotoAdvDetail(id) {
console.log(id);
this.$router.push({ path: "/detail", query: { id: id } });
},
// 回到顶部
gobackTop() {
// console.log("回到顶部", this.$refs.scroll);
// 第一种写法 this.$refs.scroll 拿到scroll组件里面的scroll , 然后调用里面的方法 , 第一二参数为距离, 第三个参数为时间500ms
// this.$refs.scroll.scroll.scrollTo(0, 0, 500);
// 第二种写法
this.$refs.scroll.scrollTo(0, 0, 500);
},
imageLoad(){
console.log('图片加载完触发事件');
// this.$bus.$emit('itemImageLoad')
},
},
created() {
this.gethomeSwipeList();
this.getListData();
// 监听item中图片加载完
// this.$bus.$on('itemImageLoad', () => {
// console.log(111);
// })
},
};
</script>
<style scoped lang="scss">
.home {
height: 100vh;
position: relative;
}
.content {
position: absolute;
top: 0.9rem;
bottom: 1.08rem;
left: 0;
right: 0;
overflow: hidden;
}
// 轮播图
.my-swipe {
width: 100%;
height: 4.5rem;
}
.swiper-img {
width: 100%;
height: 4.5rem;
}
// 这部分是列表
.advert-item {
margin-left: 0.24rem;
height: 2.43rem;
padding: 0.26rem 0.24rem 0;
display: flex;
justify-content: space-between;
border-radius: 0.18rem;
margin-bottom: 0.18rem;
.label {
width: 1.2rem;
height: 0.34rem;
line-height: 0.34rem;
text-align: center;
display: inline-block;
background: linear-gradient(90deg, #fecb00 0%, #feba00 100%);
border-radius: 0.08rem;
font-size: 0.2rem;
color: #fff;
}
.label2 {
background: #c3d8e6;
color: #fff;
}
.label3 {
background: #e0c19d;
color: #fff;
}
.label4 {
background: #f5f5f5;
color: #333333;
}
.adv-title {
margin-left: 0.18rem;
width: 3.5rem;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tag {
color: #8c8c8c;
max-width: 1.2rem;
}
.line {
height: 0.19rem;
background: #8c8c8c;
margin: 0 0.23rem;
position: relative;
&::after {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
right: 0;
-webkit-transform: scale(0.5, 1);
transform: scale(0.5, 1);
border-right: 1px solid #8c8c8c;
}
&:last-child::after {
border: 0;
}
}
.line-right {
height: 0.19rem;
background: #8c8c8c;
margin: 0 0.23rem;
position: relative;
&::after {
content: "";
display: inline-block;
position: absolute;
top: 0;
bottom: 0;
right: 0;
-webkit-transform: scale(0.5, 1);
transform: scale(0.5, 1);
border-right: 1px solid #8c8c8c;
}
}
.border-none {
&:last-child .line-right {
&::after {
border: 0;
}
}
}
.coin {
color: #ccc;
}
.adv-img {
width: 1.6rem;
height: 1.6rem;
border-radius: 0.18rem;
img {
width: 100%;
height: 100%;
}
}
.dist {
color: #8c8c8c;
margin-top: 0.03rem;
text-align: right;
}
}
</style>
回顶封装
<template>
<div class="back-top">
<div class="up">顶部</div>
</div>
</template>
<script>
export default {
name: "backTop",
data() {
return {};
},
created() {},
computed: {},
methods: {},
};
</script>
<style lang="scss" scoped>
.back-top {
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
color: #fff;
background: rgba(226, 34, 34, 0.4);
display: flex;
justify-content: center;
align-items: center;
position: fixed;
right: 0.2rem;
bottom: 1.6rem;
z-index: 999;
}
</style>