首页>>前端>>Vue->使用【React17】【Vue3.0】两种方式实现【瀑布流布局】

使用【React17】【Vue3.0】两种方式实现【瀑布流布局】

时间:2023-11-30 本站 点击:1

先上一张效果图:

什么是瀑布流?

瀑布流是前端的一种常见的布局,具体表现形式是多栏布局,宽度固定,高度不定。与此同时,随着页面的滚动,会不断有新的元素添加到瀑布流尾部的最低列。 常见的瀑布流有如下三种样式:

卡片流: 这种样式常见于移动端购物APP,一行只展示一件物品。随着页面的加载逐步出现更多的内容,也就是我们常说的下拉列表,算是最简单的一种瀑布流了:

 

固定式瀑布流: 这种样式图片区域大小高度保持不变。统一的高度会使整个界面看起来比较整齐。 PC端淘宝首页:

移动端淘宝某页面:

 - 交错式瀑布流: 交错式瀑布流是目前各大APP首页最常采用的布局格式,也是用户视觉上最为舒服的一种布局:    ## 实现瀑布流的几种常见布局方式 目前,市面上常见的瀑布流开源插件采用的布局方案主要有以下几种: - 绝对定位:这种布局需要在图片渲染之前得知图片的宽高,以便于每次插入图片时插入到高度最矮的那一列。 - Flex布局:这种布局也是把新增的图片插入到高度最矮的一列中,但不是通过绝对定位。 ## 上手实践 鉴于让后台接口直接返回图片的宽高不太现实&交错式布局难度最大。因此本次实践采用的是Flex布局的方案来实现交错式瀑布流。 ### Flex布局实现瀑布流的过程 - 第一步:明确瀑布流有多少列,假设为x - 第二步:从瀑布流图片接口列表中取出前x个元素,依次渲染至每一列的第一行 - 第三步:从第x+1个元素开始(**此步是精髓**)   - 首先计算每一列的高度   - 然后将当前要添加的元素添加至高度最低的那一列中 - 循环第三步,直至所有元素都添加至瀑布流中 ### 实践之前的必备知识 因为在渲染当前图片前,需要得知每一列的高度,因此在添加当前图片至瀑布流之前,我们需要保证前一张添加的图片已出现在页面上。那如何得知前一张图片已经渲染成功呢?并且如何在前一张图片渲染成功之后再添加新的图片呢?   这就涉及到VueReact的生命周期,以及IntersectionObserver API的概念了: #### 何为IntersectionObserver? ##### IntersectionObserver结构 IntersectionObserver(交叉观察器)可以自动监听元素是否进入了设备的可视区域之内,而不需要通过频繁的计算(比如我们常见的根据滚动条是否触底来做的一些判断)。由于可见的本质是,目标元素与视口产生一个交叉区,所以这个API叫做“交叉观察器”。   通过上面简述,其实我们常提的图片懒加载就可以采用IntersectionAPI来实现呀,这样也免去了与滚动条的距离计算,才是上上策~ ```javascript let observerObj = new IntersectionObserver(callback, option); ``` Intersection是浏览器原生提供的构造函数,接收两个参数: - callback: 可见性发生变化时的回调函数,包含changes和observer两个参数 - option:配置对象(可选) 构造函数的返回值是一个观察器实例。实例一共有4个方法: - observe: 开始监听特定元素 - unobserve: 停止监听特定元素 - disconnect: 关闭监听工作 - takeRecords: 返回所有观察目标的对象数组 callback回调函数的第一个参数changes是一个数组,该数组的每一项都是一个IntersectionObserverEntry对象   ##### IntersectionObserverEntry对象 IntersectionObserverEntry对象是我们本文实现尾部追加元素的重要属性之一!该对象内部包含如下几个属性: - boundingClientRect:目标元素的矩形区域的信息 - intersectionRatio: 目标元素的可见比例,即intersectionRect占boundingClientRect的比例。完全可见时为1,完全不可见时小于等于0 - intersectionRect:目标元素与视口(或根元素)的交叉区域的信息 - isIntersecting: 布尔值,目标元素与交集观察者的根节点是否相交(**常用**) - isVisible: 布尔值,目标元素是否可见(该属性还在试验阶段,不建议在生产环境中使用) - rootBounds: 根元素的矩形区域额的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null - target: 被观察的目标元素,是一个DOM节点对象(**常用**) - time: 可见性发生变化的时间,是一个高精度时间戳,单位为毫秒 在本文要实现的瀑布流中,IntersectionObserver的使用如下: ```javascript // 瀑布流布局:取出数据源中最靠前的一个并添加到瀑布流高度最小的那一列,等图片完全加载后重复该循环 let observerObj = new IntersectionObserver(     (entries) => {         for (const entry of entries) {             const { target, isIntersecting } = entry             if (isIntersecting) {                 // 添加下一张图片                 addPicture()                 // 取消监听当前已加载的图片                 observerObj.unobserve(target)             }         }     },     {       rootMargin: '0px 0px 300px 0px', // 提前加载     }, ) ``` ##### 在Vue中,使用nextTick实现异步添加 nextTickVue中异步调用DOM的解决方案,它可以保证我们前一张图片渲染至页面上之后,再执行下一次渲染的操作,个人认为,有点类似于onMounted钩子函数: ```javascript nextTick(() => {         columnArray = document.querySelectorAll('.flex-column')[index].querySelectorAll('.flex-column-ele');         // 添加交叉监听器         observerObj.observe(columnArray[columnArray.length - 1])  }) ``` ##### 在React中,使用useEffect实现渲染后添加 在React中,useEffect的执行时机是页面渲染完成之后,因此,我们只需要把监听上一张图片是否渲染完成,以及加载下一张图片的函数在useEffect里引入即可: ```javascript useEffect(() => {     if (dataList.length > 0) {// 跳过页面初始化         console.log('添加图片')         addPicture()     } }, [hasGet]) ``` ### Vue3.0利用flex实现瀑布流源码 ```typescript

                       

{{ curItem.desc }}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Vue/3754.html