首先,el-scrollbar组件包住一个被内容撑开的横向列
<el-scrollbar ref="scrollbar" class="scrollbar" v-if="list.length !== 0">
<div class="step">
<div class="event-item" v-for="item in list" :key="item.id">
<div class="item-card" @click="detail(item.id)">
......
div>
div>
div>
el-scrollbar>
获取el-scrollbar的scrollWidth(元素实际宽度,包括超出隐藏的部分),减去el-scrollbar的scrollLeft(元素距离左边窗口的距离),再减去el-scrollbar的clientWidth(元素包括padding、内容区的宽度,不含边框),得到可以向右移动的最边界位置。点击一次按钮,给scrollLeft或scrollRight赋一次值以更改位置。
// 滚动
handelScroll(action) {
var scrollbar = this.$refs.scrollbar.wrap;
// 点击按钮移动一次的步长
var width = 500;
// 向右可以移动的距离
let scrollRight =
scrollbar.scrollWidth -
scrollbar.scrollLeft -
scrollbar.clientWidth;
if (action == "left") {
if (scrollbar.scrollLeft > width) { // 判断滚动到最右时
scrollbar.scrollLeft -= width;
} else {
scrollbar.scrollLeft -= scrollbar.scrollLeft;
}
} else {
if (scrollRight > width) { // 判断滚动到最右时
scrollbar.scrollLeft += width;
} else {
scrollbar.scrollLeft += scrollRight;
}
}
}
is-horizontal隐藏el-scrollbar自身的滚动条
::v-deep .scrollbar {
.is-horizontal {
height: 0;
left: 0;
}
}
横向排列宽度由内容撑开需要父元素加入white-space:nowrap,子元素加入display: inline-block;
.step {
height: 540px;
white-space: nowrap;
padding-top: 50px;
.event-item {
width: 320px;
height: 100%;
display: inline-block;
}
}
<template>
<div class="base-step">
<div class="loading" v-if="subLoading">
<div class="loading-tip">
<i class="el-icon-loading">i>
<div class="tip">
加载中
div>
div>
div>
<el-scrollbar ref="scrollbar" class="scrollbar" v-if="list.length !== 0">
<div class="step">
<div class="event-item" v-for="item in list" :key="item.id">
<div class="item-card" @click="detail(item.id)">
<img :src="item.image ? item.image.split(',')[0] : require('@/assets/images/home/lack.png')" class="item-img" />
<div class="item-content">
<div class="info-box">
<div class="info-title">{{ item.name }}div>
<div class="star-box">
<img v-for="star in item.star" :key="star" class="star" src="@/assets/images/heaven/icon_grade.png" />
div>
<div class="info-item-box">
<div class="info-item">
<img class="info-item-icon" src="@/assets/images/heaven/2_icon_date.png" />
<div class="info-item-value">
{{ item.startTime && item.endTime ? item.startTime + '-' + item.endTime : "暂无信息" }}
div>
div>
div>
<div class="info-item-box">
<div class="info-item">
<img class="info-item-icon" src="@/assets/images/heaven/2_icon_iphone.png" />
<div class="info-item-value">
{{ item.phone ? item.phone : "暂无信息" }}
div>
div>
div>
<div class="info-item-box">
<div class="info-item">
<img class="info-item-icon" src="@/assets/images/heaven/2_icon_map.png" />
<div class="info-item-value address">
{{ item.adress ? item.adress : "暂无信息" }}
div>
div>
div>
div>
div>
div>
div>
div>
el-scrollbar>
<div class="pagination-scroll" v-if="list.length !== 0">
<base-pagination direction="horizontal" type="scroll" @pageChange="handelScroll">base-pagination>
div>
<div class="empty" v-if="list.length === 0 && !subLoading">
<div class="block">
<template v-if="onLine">
<img class="image" src="@/assets/images/home/no_data.png" alt="">
<div class="tip">
{{ emptyTip }}
div>
template>
<template v-if="!onLine">
<img class="image" src="@/assets/images/home/no_net.png" alt="">
<div class="tip">
网络未连接,请检查网络配置
div>
template>
<div class="reload" @click="reLoadClick">
重新加载
div>
div>
div>
div>
template>
<script>
export default {
name: "baseStep",
data() {
return {
onLine: navigator.onLine,
subLoading: true
};
},
watch: {
loading(val) {
this.subLoading = val;
}
},
props: {
list: {
type: Array,
default: () => {
return []
}
},
detailRoute: {
type: String,
default: () => {
return ''
}
},
emptyTip: {
type: String,
default: '暂无数据'
},
loading: {
type: Boolean,
default: true
},
// 重载函数
reLoad: {
type: Function,
default: () => {}
}
},
mounted() {
window.addEventListener('online', this.updateOnlineStatus);// 网络由异常到正常时触发
window.addEventListener('offline', this.updateOnlineStatus);// 网络由正常常到异常时触发
},
methods: {
detail(id) {
if (this.detailRoute) {
this.$router.push(this.detailRoute + '?id=' + id)
}
},
// 滚动
handelScroll(action) {
var scrollbar = this.$refs.scrollbar.wrap;
var width = 500;
let scrollRight =
scrollbar.scrollWidth -
scrollbar.scrollLeft -
scrollbar.clientWidth;
if (action == "left") {
if (scrollbar.scrollLeft > width) { // 判断滚动到最右时
scrollbar.scrollLeft -= width;
} else {
scrollbar.scrollLeft -= scrollbar.scrollLeft;
}
} else {
if (scrollRight > width) { // 判断滚动到最右时
scrollbar.scrollLeft += width;
} else {
scrollbar.scrollLeft += scrollRight;
}
}
},
reLoadClick() {
this.reLoad();
},
updateOnlineStatus(e) {
const { type } = e;
this.onLine = type === 'online';
},
beforeDestroy(){
window.removeEventListener('online', this.updateOnlineStatus);
window.removeEventListener('offline', this.updateOnlineStatus);
}
},
};
</script>
<template>
<div class="base-pagination">
<div class="vertical" v-if="direction == 'vertical'">
<div @click="prevPage">
<img class="image" src="../../assets/images/home/btn_up.png" alt="" />
div>
<div class="pager" v-if="type == 'pagination'">
{{ currPage }} / {{ totalPages }}
div>
<div @click="nextPage">
<img class="image" src="../../assets/images/home/btn_down.png" alt="" />
div>
div>
<div class="horizontal" v-else>
<div @click="prevPage">
<img class="image" src="../../assets/images/home/btn_left.png" alt="" />
div>
<div class="pager" v-if="type == 'pagination'">
{{ currPage }} / {{ totalPages }}
div>
<div @click="nextPage">
<img
class="image"
src="../../assets/images/home/btn_right.png"
alt=""
/>
div>
div>
div>
template>
这个按钮组件预留了翻页、纵向的功能
<script>
export default {
name: "basePagination",
data() {
return {
currPage: 0,
totalPages: 0, // 总页数
};
},
props: {
// 方向 垂直vertical | 水平horizontal
direction: {
type: String,
default: "vertical",
},
pager: {
type: Object,
default: () => {
return {
currPage: 0,
totalPages: 0,
};
},
},
// 类型 pagination 分页 | scroll 滚动
type: {
type: String,
default: "pagination",
},
},
mounted() {
if (this.type == "pagination") {
this.getPager();
}
},
methods: {
getPager() {
this.$nextTick(() => {
this.currPage = parseInt(this.pager.currPage);
this.totalPages = parseInt(this.pager.totalPages);
});
},
// 上一页
prevPage() {
if (this.type == "pagination") {
if (this.currPage > 1) {
this.currPage--;
this.$emit("pageChange", this.currPage);
}
} else if (this.type == "scroll") {
if (this.direction === "vertical") {
this.$emit("pageChange", "up");
} else if (this.direction === "horizontal") {
this.$emit("pageChange", "left");
}
}
},
// 下一页
nextPage() {
if (this.type == "pagination") {
if (this.currPage < this.totalPages) {
this.currPage++;
this.$emit("pageChange", this.currPage);
}
} else if (this.type == "scroll") {
if (this.direction === "vertical") {
this.$emit("pageChange", "down");
} else if (this.direction === "horizontal") {
this.$emit("pageChange", "right");
}
}
},
},
};
</script>