Anthony Fu @ antfu.me

瀑布流增加监听器加载图片以及移除瀑布流数据

Mar 31 · 10min

JavaScript

瀑布流改进-增加监听时间加载图片保证渲染时能获取正确的元素高度


当瀑布流中的元素包含图片并且尺寸不明确的时候(更佳的做法是在图片文件中包含图片尺寸信息,来提升前端的渲染体验),监听每一次图片加载的load状态,当图片loaded,则进行获取高度插入下一组瀑布流数据。

在上次基础上进行一些改动,下面是代码,还增加了reduce的生成器,用于处理移除瀑布流数据的情况。

实例效果预览图

实例展示效果

Template and CSS

 <div class="content">
    <div class="list" ref="l1">
      <TransitionGroup name="add">
        <div class="item" v-for="(i1, index1) in list1" :key="index1"><img :src="i1.img" ref="imgs">{{
          i1.text }}</div>
      </TransitionGroup>
    </div>
    <div class="list" ref="l2">
      <TransitionGroup name="add">
        <div class="item" v-for="(i2, index2) in list2" :key="index2"><img :src="i2.img" ref="imgs">{{ i2.text }}</div>
      </TransitionGroup>
    </div>
  </div>

Script

import { onMounted, ref, watch } from 'vue';

interface Data {
  text: string,
  img?: string,
}
const data = ref<Data[]>([
  { text: '图文一', img: 'https://live.mdnplay.dev/zh-CN/docs/Web/HTML/Element/img/favicon144.png' },
  { text: '图文二图文二' ,img: 'https://live.mdnplay.dev/zh-CN/docs/Web/HTML/Element/img/clock-demo-400px.png'},
  { text: '图文三图文三图文三' ,img: 'https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg'},
  { text: '图文四图文四图文四图文四' ,img: 'https://interactive-examples.mdn.mozilla.net/media/examples/balloon-small.jpg'},
  { text: '图文五图文五图文五图文五图文五' ,img: ''}
])
const imgs = ref([])
const i = ref(0)

const list1 = ref<Data[]>([])
const list2 = ref<Data[]>([])
const l1 = ref()
const l2 = ref()

function* addData() {
  if (i.value != data.value.length) {
    if (l1.value.offsetHeight <= l2.value.offsetHeight) {
      yield list1.value.push(data.value[i.value++])
    } else {
      yield list2.value.push(data.value[i.value++])
    }
  }
}

function* reduceData() {
  if (i.value != -1) {
    if (l1.value.offsetHeight > l2.value.offsetHeight) {
      i.value--
      yield list1.value.splice(list1.value.length - 1, 1)
    } else {
      i.value--
      yield list2.value.splice(list2.value.length - 1, 1)
    }
  }
}

watch(i, (newV, oldV) => {
  console.log(l1.value.offsetHeight, l2.value.offsetHeight)
  if (newV > oldV) {
    setTimeout(() => {
      console.log(imgs.value)
      imgs.value[imgs.value.length-1].addEventListener("load", () => {
        console.log('loaded')
        addData().next()
      });
    }, 120);
  } else {
    setTimeout(() => {
      reduceData().next()
    }, 200);
  }

})

onMounted(() => {
  addData().next()
})
>