当前位置: 首页 > news >正文

长春专业做网站公司排名网站建站模板

长春专业做网站公司排名,网站建站模板,dw制造网站log怎么做,适合个人站长的网站有哪些实现思路:Vue 子组件高度不固定下实现瀑布流布局 一、瀑布流布局基础实现原理 在深入解说不定高度子组件的瀑布流如何实现之前,先大体说一下子组件高度固定已知的这种实现原理: 有一个已知组件高度的数组。定义好这个瀑布流的列数&#xff…

实现思路:Vue 子组件高度不固定下实现瀑布流布局

在这里插入图片描述

一、瀑布流布局基础实现原理

在深入解说不定高度子组件的瀑布流如何实现之前,先大体说一下子组件高度固定已知的这种实现原理:

  1. 有一个已知组件高度的数组。
  2. 定义好这个瀑布流的列数,每列的宽度。
  3. 放置这些子组件的容器设置 position: relative 属性,内部子组件设置 position: absolute 属性,也就是说子组件可以在容器中以 left: --px; top: --px 的方式随意定位。
  4. 依次放置子组件,并记录离顶部最小距离的列数和位置值。下一个子组件的放置位置就是这里。
  5. 按照上面的的操作依次放置数组内所有元素到 dom。

二、我的需求

能看到上面瀑布流的实现前提,是需要每个子组件都有明确固定高度。
而我有一场景是:子组件的高度不能提前知道,它的高度由组件内部的文本多少来决定,它能显示多高就显示多高。
像这种,就需要在渲染过程中去判断最后一个合理的放置位置。

三、子组件动态高度的瀑布流,实现原理

搞了一整天,总算搞出来了,效果还可以。
这个渐进的过程是我添加了一个 timeout 实现的,实际可以更快的刷出来。

在这里插入图片描述


用一句话概括就是:
找到每列中最后可放置位置的 top 值,对比出最小的,作为下一个元素的放置位置。


Vue 实现瀑布流的问题是,Vue 是数据驱动的,就需要在渲染之前就知道每个组件的具体位置。而这,是无法一次性实现的,只能一一去把元素添加了待显示的数组中,当每个元素添加之后,再去计算下一个组件的放置位置。

说一下实现原理,知道原理之后,需要的只是如何实现它。

  1. 定义好你要显示多少列 colCountarrayOrigin 放置原始的数组, arrayShow 用于列表渲染,过程就是将 arrayOrigin 内的元素依次添加到 arrayShow 中,这个过程中去给每个元素添加 top left 位置值
  2. 第一行内部的展示不需要考虑高度值,因为都是 top: 0,放置的时候要标记自己是哪一列,后面会用到。
  3. 依次放置每个子组件到容器中,由于高度是不定的,需要到 nextTick 里面去放置下一个组件,这里可以通过递归的方式去放置,直到元素数量与要放置的元素数量一致。
  4. 后面的只需要查找容器里的最后 colCount + 1 个组件的位置,在每一列中找出每个子组件 offsetTop + offsetHeight 最小值的位置,并标记这个 col 列数,作为放置下一个组件的位置。
  5. 依次执行,直到放完。

在这里插入图片描述

取多少个子组件作为缓存合适?

按照上面的逻辑去实现之后,你会遇到一个新的问题:
在获取容器中最后几个子组件,并获取到每列距离 top 最小的值的时候,可能会略过某列。原因是这个 colCount + 1 的缓存区的数量太小。

像下面这张图一样,如果只取 colCount + 1 个元素的值去计算高度,那么就会忽略前面第二列的高度值。错误的放置在了红色位置。

在这里插入图片描述
原因就是在向后追溯最后 colCount + 1 个元素的时候,这个数量不足以覆盖所有列。如下图,至少需要向上找 13 个元素才可以。
所以我的这个页面中取了上 50 个。

在这里插入图片描述

四、完整代码

看源码吧,这是我在我一个开源项目《标题日记》中实现的一个功能。

github 页面源码: https://github.com/KyleBing/diary/blob/master/src/page/listHole/ListHole.vue
《标题日记》github: https://github.com/KyleBing/diary

主要的代码部分,不完整,完整的请看上面的源码

/*** 列表渲染*/
const diariesShow = ref<Array<DiaryEntityHole>>([])  // 列表展示的日记
const loadGap = 100 // 卡片加载间隔时长,单位 ms
const isShowLoadProcess = true // 是否显示卡片加载的过程const colCount = 10 // 列数
let lastDiaryIndex = 1  // 最后一个日记的 index
let lastTopPos = 0  // 最后一个日记的末尾位置: 距离 TOP
let lastCol = 0  // 下次该放置的 col index,哪一列
let colWidth = storeProject.insets.windowsWidth / colCount  // 每个元素的宽度const loadTimeOutHandle = ref()  // 载入过程的 timeOut handle
const isNeedLoadNextTimeout = true  // 是否要打断 timeout 的载入过程function renderingHoleList(newDiaries: Array<DiaryEntityDatabase>, index: number){// 如果不需要载入下面的内容,在 reload 的时候会遇到这种情况if (!isNeedLoadNextTimeout){return}// 1. 转成 DiaryEntityHole 对象let diary = newDiaries[index] as DiaryEntityHolediary.position = {top:  lastTopPos,left: lastCol * colWidth,col: lastCol}// 2. 添加到展示的列表中diariesShow.value.push(diary)nextTick(()=>{// 3. 待其渲染完成后再去处理下一个let domItems = Array.from((document.querySelector('.diary-list-hole') as HTMLDivElement).children) // Elements 转成数组// 3.1 第一排,前 colCount 个是不需要知道位置的,因为 top 都为 0if (lastDiaryIndex < colCount - 1){lastCol = lastCol + 1lastTopPos = 0}// 3.2 以后其它的else {// 取后 colCount 个元素的 lastTopPoslet countInDomItems = domItems.length > 50? domItems.slice(domItems.length - 50):domItemslet domItemsHeightColArray = countInDomItems.map(item => {let dom = item as HTMLDivElementlet col = Number(dom.getAttribute('data-col'))let posTop = dom.offsetTop + dom.offsetHeightreturn {posTop,col}})// Map 放置第 col 的最大高度值,这里用 Map 或 Set 都可以,反正就是为了使值唯一let everyColLastMaxPosMap = new Map()  // [2,345],[3,234],[4,456]domItemsHeightColArray.forEach(item => {// 获取已经存在的 lastPoslet existColPos = everyColLastMaxPosMap.get(item.col)if (existColPos === undefined){everyColLastMaxPosMap.set(item.col, item.posTop)} else {if (item.posTop >= existColPos){ // 如果有更大的,使用最大的everyColLastMaxPosMap.set(item.col, item.posTop)}}})// 将 Map 转成数组let everyColLastPosArray: Array<{posTop: number, col: number}> = []everyColLastMaxPosMap.forEach((value, key) => {everyColLastPosArray.push({posTop: value,col: key})})everyColLastPosArray.sort((a,b) => b.col - a.col) // 小值在前.sort((a,b) => a.posTop - b.posTop) // 大值在前lastTopPos = everyColLastPosArray[0].posToplastCol = everyColLastPosArray[0].col// console.log(`${lastDiaryIndex}: `, lastTopPos, lastCol,  everyColLastPosArray, domItemsHeightColArray)}// 4. index + 1index = index + 1lastDiaryIndex = lastDiaryIndex + 1// 5. 退出递归条件if (index < newDiaries.length){if (isShowLoadProcess){loadTimeOutHandle.value = setTimeout(()=>{renderingHoleList(newDiaries, index)}, loadGap)} else {renderingHoleList(newDiaries, index)}}})
}
http://www.mnyf.cn/news/43702.html

相关文章:

  • 有什么做房屋装修的网站网站快照优化公司
  • 做手机网站费用青岛网站制作公司
  • 外贸网站建设需要注意事项网站推广方式有哪些
  • 高密做网站seo怎么收费
  • 浏览器缓存 wordpress哈尔滨优化网站方法
  • 网站制作前期十大搜索引擎神器
  • qq 网站在线客服seo门户网站优化
  • 360网站地图怎么做qq群推广网站免费
  • 校园网子网站建设管理意见或策划seo网站关键词优化机构
  • 微网站获取访客手机seo网站关键词优化价格
  • 弥勒网站设计公司游戏推广平台哪个好
  • 做图软件ps下载网站樱桃电视剧西瓜视频在线观看
  • 微信小程序平台官网登录网站优化外包顾问
  • 先建网站还是先做app好广州市疫情最新情况
  • 网站的流程图软件开发公司推荐
  • 深圳网站建设服务公精准引流怎么推广
  • 中职网站建设课件杭州关键词排名工具
  • 北京做网站个人成都官网seo费用
  • 网站做电源营销网站建设
  • 电商网站设计规范口碑营销策略有哪些
  • 网站不支持ie8网络推广项目外包公司
  • 北京网站制作多少钱郑州学校网站建设
  • 什么网站可以做时间加减优化落实疫情防控
  • 做赌博彩票网站山东济南最新消息
  • 安徽省建设厅焊工证查询网站制作网站费用
  • 网站建设 网站推广免费正能量erp软件下载
  • 建设执业资格管理中心网站软文范例大全100字
  • 萧江做网站适合中层管理的培训
  • 东莞seo关键词优化seo关键词优化软件怎么样
  • pcms网站开发平台推广策划方案