🔢瀑布流在知名网站的应用
瀑布流布局广泛应用于花瓣网、堆糖等典型网站,为用户提供了独特的浏览体验。
♐瀑布流布局的核心原理
🍧设计思路概述
页面布局首先确保宽度相等,长度不同的特点,需要运用绝对定位的思想。前五个元素正常排列,从第六个开始,需要找到最矮的列进行追加。
📝如何确定最矮的一列?
首个元素较易获取,而后续每个盒子可以获取其高度,从中找到最矮的盒子,并获取其定位信息。
新追加盒子的定位计算:
left:最矮盒子的索引 * (盒子的宽度 + 左右间距)
top:该盒子的高度 + 上下间距
追加后更新列高度,记录并生成新的高度,进行下一轮的比较,依此类推。水fall是一个基于jQuery的组件,实现了这一布局和动态渲染。
🌈具体实现思路
外侧左右两边无间距,对于5列布局,共有4个间距。在给定宽度width的情况下,通过以下公式计算间距space:
JavaScript代码:
第一排盒子的定位:
top:0
left:索引 * (width + space)
第二排盒子的定位:
top:minHeight + space
left:索引 * (width + space)
因此,5列的高度可用一个数组表示,便于找到最矮元素及其索引。
🔄插件封装:优化瀑布流布局的代码重用性
为了在首次加载和后续加载时都能方便地应用瀑布流布局,我们将瀑布流布局的方法进行插件封装,以实现代码的复用。
首先,了解瀑布流的HTML布局:
下面我们将使用 jQuery 封装一个插件。
🚀第一步:将jQuery中的全局变量局部化,提升性能与防止全局污染
为了避免全局变量的污染并提高性能,我们可以将jQuery中的全局变量转化为局部变量,形成一个闭包。在闭包中定义的变量不会影响到外部环境。
🚀第二步:利用jquery.fn.extend扩展插件方法
jQuery中的fn函数提供了一个第三方插件方法的入口,用于扩展jQuery元素集(通过$获取的元素)。这样可以方便地添加新的方法,通常用于制作插件。
🚀第三步:对首排进行瀑布流布局
通过以上代码,我们完成了首排元素的瀑布流布局。在遍历每个子元素时,前列的元素被正确定位在顶部,并对应的高度被记录在数组中。打印高度数组可以看到前5个元素的高度都被成功存储,为后续的布局工作打下了基础。在效果图中,由于模拟了13个盒子,因此余下的盒子叠在一起。
🚀第四步:对余下的元素进行瀑布流布局
通过以上代码,我们成功实现了对余下元素的瀑布流布局。在遍历每个子元素时,前列的元素被正确定位在顶部,而后续的元素会根据最矮的一列进行排列。打印高度数组,我们可以观察到元素的正确排列和高度更新。最终,通过设置父容器的高度,确保瀑布流布局的整体美观。在效果图中,可以清晰看到元素被按照瀑布流的形式排列,为加载更多元素创造了合适的位置。
🚀第五步:在HTML中调用瀑布流布局
通过以上代码,我们确保了在页面上所有资源加载完成后再调用瀑布流布局方法,避免了在网络速度较慢的情况下出现图片未加载完毕导致盒子重叠的问题。使用window.onload确保了整个页面的资源都已加载完成,从而获取到了图片的尺寸来撑开盒子的高度,实现了瀑布流布局的正常展示。而相比之下,jQuery的$(function(){})方法是在DOM元素加载完成后就会执行,可能会在图片加载前就进行布局,导致视觉上的问题。
⛲动态渲染
由于数据量庞大,我们将采用分批次渲染的方式。下面是原理图:
接口文档:
接口说明: 瀑布流分页数据
接口地址: data.php
请求方式: GET
接口参数:
page: 当前页码
pageSize: 当前页要显示的条数
返回类型: JSON
返回数据格式:
page: 下一页的页码(根据页码获取下一页的数据)
items: 返回当前页的数据
path: 图片地址
text: 文字
此时我们需要准备好容器的"壳子":
以上是用于动态渲染数据的基础结构,我们将使用data.php接口来获取瀑布流分页数据,确保数据的分批次加载,提高页面加载效率。
🌌需求分析
在加载第一页时,我们有以下步骤:
使用 AJAX 加载第一页的数据。
按钮应显示为“加载更多”状态。
加载完成后,将数据渲染到页面中,可以使用 artTemplate 来简化渲染过程。
将渲染完成的页面初始化成瀑布流布局,使用 waterfall 插件实现。
在加载下一页时,我们有以下步骤:
加载数据的方式可以是手动加载(点击按钮加载下一页的数据)或自动加载(当滚动到底部时主动加载下一页)。
按钮应显示为“正在加载中...”,并禁用以防止重复提交。
加载完成后,将数据渲染到页面中。
将渲染完成的页面重新初始化为瀑布流布局。
按钮应再次显示为“加载更多”。
当没有更多数据可加载时,按钮应被禁用,并显示“没有更多数据了”。
通过以上步骤,我们能够实现对分页数据的加载、渲染和瀑布流布局的管理。这样的流程旨在提供用户友好的交互体验,确保数据按需加载,并且按钮状态的变化能够反映加载的进度和状态。
🃏渲染第一页数据
在加载页面时,我们会使用到加载数据、渲染页面、以及初始化瀑布流这三个步骤。为了提高代码的复用性,我们将这三个功能封装到一个函数中。首先,我们着手实现第一个功能:
通过以上代码,我们实现了渲染第一页数据的功能。在加载页面时,我们调用 render 函数,该函数发送 AJAX 请求获取数据,成功后输出数据到控制台。
这是我们完成第一页数据渲染的第一步。
🌖渲染页面
为了渲染页面,我们首先准备了一个模板,用于定义数据展示的结构。以下是模板的代码:
在 JavaScript 中,我们通过 AJAX 请求获取数据,并使用模板引擎将数据渲染到页面中,然后进行瀑布流布局。以下是实现这一功能的代码:
通过上述代码,我们完成了页面的渲染过程。数据被加载后,使用模板引擎将其渲染到页面中,并通过瀑布流布局使页面呈现出良好的展示效果。最后,我们修改了按钮的状态,使其显示为“加载更多”以便用户进行下一步操作。
💞第二页面的渲染(手动加载)
在第二页的渲染中,我们需要做一些调整:
添加按钮的点击事件,以便在按钮点击时进行渲染。
在按钮点击加载数据时,为了避免发送多个 AJAX 请求,需要给按钮加锁。在按钮处于 loading 状态时,不进行数据渲染。
在 render 函数中,在改变按钮状态之前,使用自定义属性记录下一页需要获取的页数。我们使用 jQuery 的 data() 方法,在其中传递一个 page 参数,将其保存在 data.page 中。在获取数据时,从按钮的 data 中获取 page 的值。初次加载时,data.page 为空,因此我们设定默认值为 1。
在 render 函数中,在数据成功加载之前,按钮仍然处于 loading 状态。因此,我们添加了 beforeSend 函数,用于设置 loading 状态。
在渲染时,通过判断返回的数组中的长度是否为零,来确定是否还有更多的数据。如果长度为零,说明没有更多数据了。
以下是相应的代码:
通过这些调整,我们完成了第二页面的手动加载数据的渲染过程,确保了在用户点击按钮时正确获取并渲染下一页的数据。
💞第二页面的渲染(滚动加载)
原理图
在滚动加载的情况下,我们需要根据页面滚动位置的不同来判断何时触发下一次的数据请求。以下是相应的代码:
这段代码中,我们通过监听滚动事件,计算页面各个位置的参数,当页面滚动到距离底部小于200px时,触发下一次的数据加载。同时,为了避免多次加载,我们在按钮处于 loading 状态时不再触发加载。
🤏特别注意的问题
在动态加载页面时,我们面临了一个问题,即如何处理在拿到后台数据后,将其转化成 HTML 并添加到页面上,然后再开始加载图片。之前我们在静态加载页面时使用了 window.onload 来确保页面上的所有资源都加载完成后再进行渲染,以避免页面重叠现象的发生。
然而,在动态加载页面时,我们需要考虑到图片加载的问题。一种解决方法是等待所有图片加载完成后再进行页面渲染,但这可能会导致较长的等待时间,不够合理。我们可以借鉴类似花瓣网的做法,即在加载图片时进行宽高的设定,但这个大小应根据原图片的尺寸进行等比例的缩放。
以花瓣网为例,加载图片时进行了宽高的设定,但这个大小是根据原图片的尺寸进行缩放计算的。
这样,通过使用 width 变量,我们可以在加载图片时进行按比例缩放,从而保持瀑布流的完整性。