帝国cms怎么做电影网站建设网站要钱吗

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

帝国cms怎么做电影网站,建设网站要钱吗,江门seo外包服务,建设部指定招标网站实现思路#xff1a;Vue 子组件高度不固定下实现瀑布流布局 一、瀑布流布局基础实现原理 在深入解说不定高度子组件的瀑布流如何实现之前#xff0c;先大体说一下子组件高度固定已知的这种实现原理#xff1a; 有一个已知组件高度的数组。定义好这个瀑布流的列数#xff…实现思路Vue 子组件高度不固定下实现瀑布流布局 一、瀑布流布局基础实现原理 在深入解说不定高度子组件的瀑布流如何实现之前先大体说一下子组件高度固定已知的这种实现原理 有一个已知组件高度的数组。定义好这个瀑布流的列数每列的宽度。放置这些子组件的容器设置 position: relative 属性内部子组件设置 position: absolute 属性也就是说子组件可以在容器中以 left: –px; top: –px 的方式随意定位。依次放置子组件并记录离顶部最小距离的列数和位置值。下一个子组件的放置位置就是这里。按照上面的的操作依次放置数组内所有元素到 dom。 二、我的需求 能看到上面瀑布流的实现前提是需要每个子组件都有明确固定高度。 而我有一场景是子组件的高度不能提前知道它的高度由组件内部的文本多少来决定它能显示多高就显示多高。 像这种就需要在渲染过程中去判断最后一个合理的放置位置。 三、子组件动态高度的瀑布流实现原理 搞了一整天总算搞出来了效果还可以。 这个渐进的过程是我添加了一个 timeout 实现的实际可以更快的刷出来。 用一句话概括就是 找到每列中最后可放置位置的 top 值对比出最小的作为下一个元素的放置位置。 Vue 实现瀑布流的问题是Vue 是数据驱动的就需要在渲染之前就知道每个组件的具体位置。而这是无法一次性实现的只能一一去把元素添加了待显示的数组中当每个元素添加之后再去计算下一个组件的放置位置。 说一下实现原理知道原理之后需要的只是如何实现它。 定义好你要显示多少列 colCount arrayOrigin 放置原始的数组 arrayShow 用于列表渲染过程就是将 arrayOrigin 内的元素依次添加到 arrayShow 中这个过程中去给每个元素添加 top left 位置值第一行内部的展示不需要考虑高度值因为都是 top: 0放置的时候要标记自己是哪一列后面会用到。依次放置每个子组件到容器中由于高度是不定的需要到 nextTick 里面去放置下一个组件这里可以通过递归的方式去放置直到元素数量与要放置的元素数量一致。后面的只需要查找容器里的最后 colCount 1 个组件的位置在每一列中找出每个子组件 offsetTop offsetHeight 最小值的位置并标记这个 col 列数作为放置下一个组件的位置。依次执行直到放完。 取多少个子组件作为缓存合适 按照上面的逻辑去实现之后你会遇到一个新的问题 在获取容器中最后几个子组件并获取到每列距离 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 refArrayDiaryEntityHole([]) // 列表展示的日记 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: ArrayDiaryEntityDatabase, 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)}}}) }