- 新增组件m-waterfall 这样就可以在页面直接使用 不用在引入了
- <template>
- <view class="m-waterfall">
- <view id="m-left-column" class="m-column">
- <slot name="left" :leftList="leftList"></slot>
- </view>
- <view id="m-right-column" class="m-column">
- <slot name="right" :rightList="rightList"></slot>
- </view>
- </view>
- </template>
- <script setup>
- /**
- * @param value 瀑布流数据
- * @param addTime 插入数据的时间间隔
- * @param keyIdData / id值,用于清除某一条数据时,根据此idKey名称找到并移除
- */
- import {
- computed,
- defineProps,
- toRefs
- } from "vue"
-
- const props=defineProps({
- // 瀑布流数据
- value: {
- required: true,
- type: Array,
- default: ()=>[]
- },
- // 每次向结构插入数据的时间间隔,间隔越长,越能保证两列高度相近,但是对用户体验越不好
- addTime: {
- type: [Number, String],
- default: 200
- },
- // id值,用于清除某一条数据时,根据此idKey名称找到并移除
- keyIdData: {
- type: String,
- default: 'id'
- }
- })
- const {
- value,
- addTime,
- keyIdData
- } = toRefs(props)
- const leftList = ref([])
- const rightList = ref([])
- const tempList = ref([])
- const copyFlowList= computed (()=> {
- return cloneData(value.value);
- })
-
- watch(()=>value.value,(nVal,oVal)=>{
- let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0;
-
- tempList.value = tempList.value.concat(cloneData(nVal.slice(startIndex)));
- splitData();
-
- })
- onMounted(()=>{
-
- tempList.value = cloneData(copyFlowList.value);
- setTimeout(()=>{
- splitData();
- },200)
- })
-
- const instance = getCurrentInstance()
- const getysHeigth=(classd)=>{
- return new Promise((resolve, reject) => {
- uni.createSelectorQuery().in(instance)
- .select(classd)
- .boundingClientRect(data => {
- if (data) {
- resolve(data);
- } else {
- reject(new Error('获取节点信息失败'));
- }
- })
- .exec();
- });
- }
- const splitData = async () => {
-
- if (tempList.value.length==0) return;
- let leftRect = await getysHeigth('#m-left-column');
- let rightRect = await getysHeigth('#m-right-column');
- // 如果左边小于或等于右边,就添加到左边,否则添加到右边
- let item =tempList.value[0];
- // 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
- // 数组可能变成[],导致此item值可能为undefined
- if (!item) return;
- if (leftRect.height < rightRect.height) {
- leftList.value.push(item);
- } else if (leftRect.height > rightRect.height) {
- rightList.value.push(item);
- } else {
- // 这里是为了保证第一和第二张添加时,左右都能有内容
- // 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
- if (leftList.value.length <= rightList.value.length) {
- leftList.value.push(item);
- } else {
- rightList.value.push(item);
- }
- }
- // 移除临时列表的第一项
- tempList.value.splice(0, 1);
- // 如果临时数组还有数据,继续循环
- if (tempList.value.length) {
- setTimeout(() => {
- splitData();
- }, addTime)
- }
- }
- // 复制而不是引用对象和数组
- const cloneData=(data)=>{
- if(data){
- return JSON.parse(JSON.stringify(data));
- }else{
- return [];
- }
-
- }
-
- </script>
- <style lang="scss" scoped>
- .m-waterfall {
- display: flex;
- flex-direction: row;
- align-items: flex-start;
- }
-
- .m-column {
- display: flex;
- flex: 1;
- flex-direction: column;
- height: auto;
- }
-
- .m-image {
- width: 100%;
- }
- </style>
复制代码 组件利用
- <m-waterfall :value="product">
- <!-- 左边数据 -->
- <template v-slot:left="{leftList}">
- <view @click="addDta" class="prodecutitem" v-for="(item,index) in leftList" :key="index">
- <view style="width: 100%;">
- <m-imgage :url="item.image"></m-imgage>
- </view>
- <view class="title">{{item.title}}</view>
- <view class="desc">{{item.title}}</view>
- </view>
- </template>
- <!-- 右边数据 -->
- <template v-slot:right="{rightList}">
- <view class="prodecutitem" v-for="(item,index) in rightList" :key="index">
- <view>
- <m-imgage :url="item.image"></m-imgage>
- </view>
- <view class="title">{{item.title}}</view>
- <view class="desc">{{item.title}}</view>
- </view>
- </template>
- </m-waterfal>
- 数据
- const product=ref([
- {
- title:'水果蔬菜1',
- image:imgSrc.value
- },
- {
- title:'水果蔬菜2',
- image:"https://img2.baidu.com/it/u=3893165480,918722033&fm=253&fmt=auto&app=120&f=JPEG?w=729&h=1215"
- },
- {
- title:'水果蔬菜3',
- image:imgSrc.value
- },
- {
- title:'水果蔬菜1',
- image:imgSrc.value
- },
- {
- title:'水果蔬菜3',
- image:imgSrc.value
- }
- ])
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |