《《高血压监狱3》法国版当生活压力遇上黑色幽默,一场法式“越狱…”》

核心内容摘要

漫画创作者的宝藏!9.1免费高清素材网站,灵感与效率齐飞!
阿娇惊艳高清美照:岁月沉淀的女神风采,一眼万年!

爱不释手!“我爱搞g52”版本更新,一次触及灵魂的进化!

该源码来自 uviewpro 地址为https://uviewpro.cn/zh/components/waterfall.html我改成vue2的写法 优化了计时器瀑布流插件templatedivclasswaterfulldivclassleftrefleftRefslot nameleft:leftListleftData/slot/divdivclassrightrefrightRefslot nameright:rightListrightData/slot/div/div/templatescript/** * * author COOBY * since

14:19 */exportdefault{props:{list:{type:Array,default:()[]},addTime:{type:Number,default:200}},data(){return{timer:null,leftData:[],rightData:[],tempList:[],}},computed:{copyFlowList(){returnthis.deepClone(this.list);}},watch:{copyFlowList(nVal,oVal){conststartIndexArray.isArray(oVal)oVal.length0?oVal.length:0;// 拼接上原有数据this.tempListthis.tempList.concat(this.deepClone(nVal.slice(startIndex)));this.splitData();},immediate:true},mounted(){this.tempListthis.deepClone(this.copyFlowList);this.splitData();},beforeDestroy(){if(this.timer)clearTimeout(this.timer);this.timernull;},methods:{asyncsplitData(){if(!this.tempList.length)return;if(!this.$refs.leftRef||!this.$refs.rightRef)return;awaitthis.$nextTick();constleftRectthis.$refs.leftRef.offsetHeight;constrightRectthis.$refs.rightRef.offsetHeight;// 如果左边小于或等于右边就添加到左边否则添加到右边constitemthis.tempList[0];// 解决多次快速上拉后可能数据会乱的问题因为经过上面的两个await节点查询阻塞一定时间加上后面的定时器干扰// 数组可能变成[]导致此item值可能为undefinedif(!item)return;if(leftRectrightRect){this.leftData.push(item);}elseif(leftRectrightRect){this.rightData.push(item);}else{// 这里是为了保证第一和第二张添加时左右都能有内容// 因为添加第一张实际队列的高度可能还是0这时需要根据队列元素长度判断下一个该放哪边if(this.leftData.lengththis.rightData.length){this.leftData.push(item);}else{this.rightData.push(item);}}// 移除临时列表的第一项this.tempList.shift();// 如果临时数组还有数据继续循环awaitthis.$nextTick();if(this.tempList.length){if(this.timer)clearTimeout(this.timer);this.timersetTimeout((){this.splitData();},Math.max(0,this.addTime));// 防止负数}},deepClone(obj,cachenewWeakMap()){if(objnull||typeofobj!object)returnobj;if(cache.has(obj))returncache.get(obj);letclone;if(objinstanceofDate){clonenewDate(obj.getTime());}elseif(objinstanceofRegExp){clonenewRegExp(obj);}elseif(objinstanceofMap){clonenewMap(Array.from(obj,([key,value])[key,this.deepClone(value,cache)]));}elseif(objinstanceofSet){clonenewSet(Array.from(obj,valuethis.deepClone(value,cache)));}elseif(Array.isArray(obj)){cloneobj.map(valuethis.deepClone(value,cache));}elseif(Object.prototype.toString.call(obj)[object Object]){cloneObject.create(Object.getPrototypeOf(obj));cache.set(obj,clone);for(const[key,value]ofObject.entries(obj)){clone[key]this.deepClone(value,cache);}}else{cloneObject.assign({},obj);}cache.set(obj,clone);returnclone;}},}/scriptstyle langlessscoped.waterfull{display:flex;gap:2vw;width:92vw;margin:0auto;.left,.right{flex:1;background-color:#fff;height:fit-content;}}/stylevue中使用waterfull:listvideoListtemplate slotleftslot-scope{ leftList }div v-for(item, index) in leftList:keyindexitemVideo:itemitem/itemVideo/div/templatetemplate slotrightslot-scope{ rightList }div v-for(item, index) in rightList:keyindexitemVideo:itemitem/itemVideo/div/template/waterfull

需求目标我们要实现一个组件具备以下能力接收一个动态变化的list数组比如通过上拉加载新增数据自动将新项“智能”分配到左列或右列使两列高度尽可能平衡支持自定义每项添加的间隔时间模拟“逐个加载”的动画效果避免因频繁更新导致的数据错乱或性能问题。

整体结构概览template div classwaterfull div classleft refleftRef slot nameleft :leftListleftData/slot /div div classright refrightRef slot nameright :rightListrightData/slot /div /div /template使用slot实现插槽分发父组件可自由定义左右列的渲染方式通过ref获取左右容器的真实 DOM 高度用于判断插入位置数据分为leftData和rightData两个数组分别控制左右列内容。

核心逻辑拆解

数据监听与增量处理watch:{copyFlowList(nVal,oVal){conststartIndexArray.isArray(oVal)oVal.length0?oVal.length:0;this.tempListthis.tempList.concat(this.deepClone(nVal.slice(startIndex)));this.splitData();},immediate:true}copyFlowList是对props.list的深拷贝避免直接修改原始数据当list变化时只取新增部分slice(startIndex)避免重复处理已有项新增项先存入tempList临时队列再交由splitData逐步分配。

✅为什么用临时队列因为我们希望“逐个”添加项带时间间隔而不是一次性塞入这样能模拟真实加载过程并防止 DOM 高度计算不准。

智能分配算法splitData这是整个组件的灵魂函数asyncsplitData(){if(!this.tempList.length)return;if(!this.$refs.leftRef||!this.$refs.rightRef)return;awaitthis.$nextTick();// 确保 DOM 已更新constleftRectthis.$refs.leftRef.offsetHeight;constrightRectthis.$refs.rightRef.offsetHeight;constitemthis.tempList[0];if(!item)return;if(leftRectrightRect){this.leftData.push(item);}else{this.rightData.push(item);}this.tempList.shift();// 移除已处理项awaitthis.$nextTick();// 等待新项渲染完成高度更新if(this.tempList.length){if(this.timer)clearTimeout(this.timer);this.timersetTimeout((){this.splitData();},Math.max(0,this.addTime));}}分配策略详解条件行为leftHeight rightHeight新项放入左边leftHeight rightHeight新项放入右边为什么不是严格而是这样能确保第一项优先放入左边第二项若高度相同都为0则进入else分支中的兜底逻辑。

兜底逻辑初始状态处理// 当左右高度相等如初始都为0时if(this.leftData.lengththis.rightData.length){this.leftData.push(item);}else{this.rightData.push(item);}防止前两项都塞到同一侧保证左右列都能有内容提升首屏体验。

异步调度与防抖每次添加一项后等待 DOM 渲染完成$nextTick()再计算下一次高度使用setTimeout控制添加频率addTime默认 200ms每次调用前clearTimeout防止多个定时器堆积尤其在快速上拉加载时。

⚠️注意如果不加$nextTick()offsetHeight可能还是旧值导致分配错误

深拷贝工具函数deepClone(obj,cachenewWeakMap()){// 处理 null、基本类型、Date、RegExp、Map、Set、Array、Object 等// 使用 WeakMap 防止循环引用}避免外部传入的对象被组件内部修改支持复杂嵌套结构适用于大多数业务场景。

样式与布局.waterfull { display: flex; gap: 2vw; width: 92vw; margin: 0 auto; .left, .right { flex: 1; background-color: #fff; height: fit-content; // 关键让容器高度随内容增长 } }使用flex: 1让左右列等宽height: fit-content确保容器高度能被 JS 正确读取offsetHeight依赖于此。

使用示例父组件中这样使用waterfull :listvideoList template slotleft slot-scope{ leftList } div v-for(item, index) in leftList :keyindex itemVideo :itemitem/itemVideo /div /template template slotright slot-scope{ rightList } div v-for(item, index) in rightList :keyindex itemVideo :itemitem/itemVideo /div /template /waterfull完全解耦渲染逻辑父组件决定如何展示每一项支持任意内容图片、卡片、文字等。

打开9.1网站-打开9.1网站应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123