Vue 瀑布流布局+触底加载下一页(原生)
效果思路1、html中建立四个“管道”2、后台获取到数据3、遍历数据,获取高度最小的管道,填入数据4、滚动条到底时触发函数,获取下一页数据,然后再执行步骤3参考jquery实现滑动到底部加载下一页的数据代码template:建立四个piping,ref参数是为了在js中获取dom元素。<template><div clas...
·
效果
思路
1、html中建立四个“管道”
2、后台获取到数据
3、遍历数据,获取高度最小的管道,填入数据
4、滚动条到底时触发函数,获取下一页数据,然后再执行步骤3
参考
代码
template:建立四个piping,ref参数是为了在js中获取dom元素。
<template>
<div class="friend_moments">
<div class="water">
<div class="piping" ref="piping0">
</div>
<div class="piping" ref="piping1">
</div>
<div class="piping" ref="piping2">
</div>
<div class="piping" ref="piping3">
</div>
</div>
</div>
</template>
script:
export default {
data() {
return {
moments: [],
available: 1,
height1: 0,
height2: 0,
height3: 0,
page: 1
};
},
created() {
// 获取第一页数据
this.fetchMoments();
},
mounted() {
// 用来监听滚轮
window.addEventListener("scroll", this.handleScroll);
},
methods: {
fetchMoments() {
// 请求接口方法
fetch("api/moments")
.then(res => res.json())
.then(res => {
this.moments = res.data;
// 分配数据到指定管道
this.sort(0);
});
},
// sort()函数是递归的,因为要确保每个卡片的图片加载完成后再获取管道的高度,但是图片加载完成的函数是个异步函数,
// 如果放在for循环中会打乱顺序,因此要使异步函数同步执行,for循环改为递归。
sort(j) {
if (j < this.moments.length) {
let that = this;
// 创建Image类
var newImg = new Image();
// 获取要加载的图片地址
newImg.src =
"http://lanyue.ink:8123/images/" +
(Math.floor(Math.random() * 15) + 1) +
".png";
// 图片加载完成后(异步)
newImg.onload = () => {
// 四个管道的高度
var arr = [
that.$refs.piping0.offsetHeight,
that.$refs.piping1.offsetHeight,
that.$refs.piping2.offsetHeight,
that.$refs.piping3.offsetHeight
];
//获取管道最小高度
var min = arr.indexOf(Math.min.apply(Math, arr));
// 添加卡片的模板
var html =
`<div class="card">
<img src=` + newImg.src + `>
<div>
<img src="http://lanyue.ink:8123/images/avatar.jpg" alt="">
<div>` + this.moments[j].id + " " + this.moments[j].content + `</div>
</div>
</div>`;
//给最小的管道添加卡片
if (min == 0) {
that.$refs.piping0.innerHTML += html;
} else if (min == 1) {
that.$refs.piping1.innerHTML += html;
} else if (min == 2) {
that.$refs.piping2.innerHTML += html;
} else if (min == 3) {
that.$refs.piping3.innerHTML += html;
}
that.sort(j + 1);
};
}
},
handleScroll() {
// 获取滚轮位置
var scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
this.height1 = scrollTop;
// 文档高度
this.height2 = document.body.scrollHeight;
// 可视区域
this.height3 =
document.compatMode == "CSS1Compat"
? document.documentElement.clientHeight
: document.body.clientHeight;
// 如果滚动到最低(这里设置离最底还有100距离才触发函数)
// available条件是为了防止触底时一直不断地请求。因此,请求一次后available设为0,直到滚动到离底部超过100距离(即数据加载玩后)才设为1
if (this.height3 + this.height1 >= this.height2 - 100 && this.available) {
//请求下一页
this.page++;
this.available = 0;
let that = this;
fetch("api/moments?page=" + this.page)
.then(res => res.json())
.then(res => {
that.moments = res.data;
if (that.moments[0]) {
that.sort(0);
} else {
that.page--;
}
});
} else if (this.height3 + this.height1 < this.height2 - 100) {
this.available = 1;
}
}
}
};
scss:
<style lang="scss">
.friend_moments {
width: 100%;
display: flex;
justify-content: center;
}
.a {
position: fixed;
width: 200px;
top: 200px;
right: 100px;
z-index: 10;
background: #eee;
}
.water {
width: 1240px;
margin-top: 60px;
display: flex;
align-items: flex-start;
margin-bottom: 100px;
.piping {
width: 25%;
padding: 10px;
padding-bottom: 0px;
}
}
.card {
width: 290px;
border-radius: 5px;
box-shadow: 0px 0px 5px #888888;
margin-bottom: 20px;
> img:first-child {
width: 100%;
border-radius: 5px;
}
> div:nth-child(2) {
display: flex;
align-items: center;
padding: 10px;
> img {
border-radius: 100%;
width: 32px;
height: 32px;
margin-right: 10px;
}
}
}
</style>
扩展
如果希望图片框大小一样,则设置图片为背景图片,cover居中显示。
1、就把scss中的card类改为:
.card {
width: 290px;
border-radius: 5px;
box-shadow: 0px 0px 5px #888888;
margin-bottom: 20px;
> div:first-child {
width: 100%;
height: 200px;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
border-radius: 5px;
}
> div:nth-child(2) {
display: flex;
align-items: center;
padding: 10px;
> img {
border-radius: 100%;
width: 32px;
height: 32px;
margin-right: 10px;
}
}
}
2、把script中html模板改成:
var html =
`<div class="card">
<div style=background-image:url(` + newImg.src + `)></div>
<div>
<img src="http://lanyue.ink:8123/images/avatar.jpg" alt="">
<div>` + this.moments[j].id + " " + this.moments[j].content + `</div>
</div>
</div>`;
修改后的效果:
这样,高度的差别就主要来自卡片的底部内容高度。
更多推荐
已为社区贡献6条内容
所有评论(0)