不等高瀑布流,ul不能设置高度,高度靠每个ul内的li撑开,
ul 不能用 flex 布局,因为会固定其他 ul 的高度,
所以只能用 float: left,浮动只针对当前 ul
代理测试
/*
瀑布流
+ 请求地址:
=> https://www.duitang.com/napi/blog/list/by_filter_id/?
include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&
filter_id=美食菜谱&
start=24&
_=1627261229774
*/
// 测试请求 - 没有问题
const obj = {
include_fields: 'top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count',
filter_id: '美食菜谱',
start: 0,
_: new Date().getTime()
}
pAjax({
url: '/dt',
data: querystringify(obj),
dataType: 'json'
}).then(res => {
console.log(res)
})
JS
// 瀑布流的逻辑代码
/*
一个小问题
+ 第一次加载的时候, img 是没有缓存的
+ 我的图片是需要去进行加载的
+ 但是, 一定是 页面结构 先到了页面上
+ 然后在开始加载图片
+ 当 li 进入到页面的时候, img 的图片还没有加载
+ 就导致一个问题, img 标签没有高, 那么所有的 li 一边高
+ 当你的 图片 加载好以后, 就导致格式不合适了
如何解决
+ 不管你的图片是不是加载了, 都给你设置好 高度
+ 把本章图片的位置先占上, 将来加载图片就不会改变 li 的高度了
图片真实宽度 页面设计宽度
---------- = -----------
图片真实高度 页面设计高度
页面设计高度 * 图片真实宽度 = 页面设计宽度 * 图片真实高度
页面设计高度 = 页面设计宽度 * 图片真实高度 / 图片真实宽度
*/
// 获取元素
const uls = document.querySelectorAll('.content > ul')
const select = document.querySelector('select')
// 准备一个变量当做开关
let flag = true
// 1. 封装一个函数, 获取高度最小的 ul
function getMinUl() {
// 问题: 如何获取到最短的 ul ?
// 1-1. 假设 [0] 的 ul 是最短的 ul
let minUl = uls[0]
// 1-2. 循环遍历 uls, 从 [1] 开始
for (let i = 1; i < uls.length; i++) {
// 1-3. 依次比较每一个 ul 的高度的 minUl 的高度
// 问题: 如何获取到 ul 的高度 ?
// 元素.offsetHeight, 获取元素的占地面积的高
if (uls[i].offsetHeight < minUl.offsetHeight) {
minUl = uls[i]
}
}
// 1-4. 把最短的 ul return 出去
return minUl
}
// 2. 获取数据
const info = {
include_fields: 'top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count',
filter_id: '美食菜谱',
start: 0,
_: new Date().getTime()
}
// 根据 info 的所有内容, 去获取本页的列表数据
getList()
async function getList() {
// 2-1. 把 info 变成 查询字符串 格式
const data = querystringify(info)
// 2-2. 发送请求
const res = await pAjax({ url: '/dt', data: data, dataType: 'json' })
// 2-3. 分析数据
// res.data.next_start 就是我们下一次需要使用的 start
// 可以直接给 info 赋值
info.start = res.data.next_start
// res.data.object_list 用来渲染页面
bindHtml(res.data.object_list)
}
// 3. 渲染页面的函数
function bindHtml(list) {
// 3-1. 循环遍历 list
// 因为 list 内每一个对象就是一个 li
list.forEach(item => {
// 先计算出每个 图片的 页面设置高度
// 页面设计高度 = 页面设计宽度 * 图片真实高度 / 图片真实宽度
const height = 280 * item.photo.height / item.photo.width
// 3-2. 组装一个 li 结构
const str = `
<li>
<div style="height: ${ height }px;" class="show">
<img src="${ item.photo.path }" alt="">
</div>
<div class="info">
<p>${ item.msg }</p>
<p>${ item.sender.username }</p>
<div class="avatar">
<img src="${ item.sender.avatar }" alt="">
</div>
</div>
</li>
`
// 3-3. 在循环内, 把 li 插入到 ul 里面
// 因为每一个 li 都有可能插入到不同的 ul 内
// 所以需要一个 li 插入一次
// 找到最短的 ul
const min = getMinUl()
min.innerHTML += str
})
// 4-6. 循环结束, 表示结构加载完毕
// 把开关打开
flag = true
}
// 4. 加载第二页
// 问题: 什么时候加载第二页 ?
// 当 浏览器卷去的高度 + 可视窗口高度 >= 最短的ul 的高度 + ul 的上方偏移量
// 4-1. 给浏览器绑定滚动事件
window.addEventListener('scroll', () => {
// 4-2. 获取该获取的数据
const scroll_top = document.documentElement.scrollTop || document.body.scrollTop
const window_height = document.documentElement.clientHeight
const min = getMinUl()
const ul_height = min.offsetHeight
const ul_top = min.offsetTop
// 4-3. 判断是否加载下一页
if (scroll_top + window_height <= ul_height + ul_top) return
console.log('执行')
// 4-4. 进行开关的判断
if (!flag) return
flag = false
// 代码能执行到这里, 说明需要加载下一页了
// 4-5. 加载下一页
// 问题: 如何加载下一页 ?
// 执行 getList()
getList()
})
// 5. 切换分类
select.addEventListener('change', () => {
// 5-1. 拿到我切换的分类
const text = select.value
// 5-2. 设置 info 的信息
info.filter_id = text
// 把 start 信息设置为 0
info.start = 0
// 把每一个 ul 清空
uls.forEach(item => item.innerHTML = '')
// 5-3. 请求数据
getList()
})
不透露我的来源地
<!-- meta 标签, name = referrer 表示来源地 -->
<!-- no-referrer 表示不透露我的来源地 -->
<meta name="referrer" content="no-referrer">
html
<div class="header">页面顶部
<select>
<option value="美食菜谱">美食菜谱</option>
<option value="家居生活">家居生活</option>
<option value="手工DIY">手工DIY</option>
<option value="时尚搭配">时尚搭配</option>
</select>
</div>
<div class="content">
<ul></ul>
<ul></ul>
<ul></ul>
<ul></ul>
</div>
<!--
<li>
<div class="show">
<img src="https://c-ssl.duitang.com/uploads/blog/202106/21/20210621182050_61c50.thumb.400_0.jpeg" alt="">
</div>
<div class="info">
<p>说明</p>
<div class="avatar">
<img src="https://c-ssl.duitang.com/uploads/avatar/202107/26/20210726074317_2c85d.thumb.100_100_c.jpeg" alt="">
</div>
</div>
</li>
-->
css
* {
margin: 0;
padding: 0;
}
ul, ol, li {
list-style: none;
}
img {
width: 100%;
height: 100%;
display: block;
}
.header, .footer, .content {
width: 1200px;
margin: 0 auto;
}
.header, .footer {
height: 100px;
background-color: skyblue;
color: #fff;
font-size: 36px;
display: flex;
justify-content: center;
align-items: center;
}
.footer {
height: 300px;
font-size: 100px;
}
.header > select {
padding: 5px 20px 5px 5px;
font-size: 20px;
}
.content {
padding: 20px 0;
overflow: hidden;
}
.content > ul {
width: 280px;
float: left;
margin: 0 10px;
}
.content > ul > li {
width: 100%;
border: 1px solid #333;
box-sizing: border-box;
margin-bottom: 10px;
}
.content > ul > li > div.show {
width: 100%;
}
.content > ul > li > div.info {
width: 100%;
height: 150px;
box-sizing: border-box;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.content > ul > li > div.info > .avatar {
width: 24px;
height: 24px;
border-radius: 50%;
overflow: hidden;
}