1. 前言
瀑布流是非常流行的一种布局方式,所以今天来玩下
2. 是什么 what
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格
哈哈以上文字摘抄自百度百科
3. 应用场景
图文混排的网站
1.png
4. 环境安装
需要的数据可以自己去爬取
5. 核心思想
多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,
根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置。
6. 直接上代码 html
<div id="app">
<div class="list">
<ul class="col" v-for="col in waterFull">
<li v-for="good in col.goods">
<img :style="{height:good.height+'px'}" v-lazy="good.img" alt="">
<h3>{{good.author}}</h3>
</li>
</ul>
</div>
</div>
7. 瀑布流
let app = Vue.createApp({
data() {
return {
list
}
},
computed: {
waterFull() {
/*
[{
h:10,
goods:[{},{},{}]
},{
h:10,
goods:[{},{},{}]
}]
*/
let arr = [];//记录每列信息
for (let i = 0; i < 5; i++) {
arr.push({
h: 0,//记录每列高度
goods: []//记录每列的数据
})
}
//分配商品
this.list.forEach(item => {
// 找最低的列
arr.sort((a, b) => a.h > b.h ? 1 : -1)
// ?w_h=236x334"
// 叠加高度
let s = item.img.split("=")[1]; //236x334
let s2 = s.split("x"); //[236,334]
let height = s2[1] / s2[0] * 200;
//经过排序最低的列在 第一个位置
arr[0].h += height; // 一列的高度
// 记录当前图片高度
item.height = height;
// 插入元素
arr[0].goods.push(item); //一列的数据
})
return arr;
}
}
})
list 是我导入的外部数据
其中 图片链接格式为
"img": "https://xx.com/3P_/fw/480/webp?w_h=236x472"
核心在于如何找到当前行最低的那列,这个只能排序 对比
arr.sort((a, b) => a.h > b.h ? 1 : -1)
凡是返回1或者大于0的正数的时候就要交换位置
所以a.h >b.h
的时候要交换位置 也就是1
8.结合懒加载
app.directive("lazy", {
mounted(el, binding) {
// 指定占位图
el.src = "./placeholder.png";
el.bindingVal = binding.value;
let timer;
el.scrollHandler = () => {
clearTimeout(timer);
timer = setTimeout(() => {
let H = window.innerHeight;
let ot = el.offsetTop;
let st = document.body.scrollTop || document.documentElement.scrollTop;
if (H + st > ot + 200) {
// 设置真实路径
el.src = el.bindingVal;
// 移除事件监听
window.removeEventListener("scroll", el.scrollHandler);
}
}, 100)
}
el.scrollHandler();//初始检测
window.addEventListener("scroll", el.scrollHandler);
},
updated(el, binding) {
// 存储新地址
el.bindingVal = binding.value;
el.scrollHandler();//初始检测
}
})
app.mount("#app")
具体懒加载思路可以参考react懒加载 ,代码其实都差不多
9. 瀑布流封装成组件
app.component("water-fall",{
props:["list","col"],
template:`
<div class="list">
<ul class="col" v-for="col in waterFull">
<li v-for="good in col.goods">
<img :style="{height:good.height+'px'}" v-lazy="good.img"
alt="">
<h3>{{good.author}}</h3>
</li>
</ul>
</div>
`,
computed: {
waterFull() {
let arr = [];//记录每列信息
for (let i = 0; i < this.col; i++) {
arr.push({
h: 0,
goods: []
})
}
//分配商品
this.list.forEach(item => {
// 找最低的列
arr.sort((a,b)=>a.h>b.h?1:-1)
// 叠加高度
let s=item.img.split("=")[1];
let s2=s.split("x");
let height=s2[1]/s2[0]*200;
arr[0].h+=height;
// 记录当前图片高度
item.height=height;
// 插入元素
arr[0].goods.push(item);
})
return arr;
}
}
})
单文件组件也一样没啥区别
再结合 懒加载的v-lazy
的指令
网友评论