intersection observer - OhMinsSup/tip-review GitHub Wiki

[https://heropy.blog/2019/10/27/intersection-observer/]

new Vue({
  el: '#app',
  data () {
    return {
      photos: [],
      length: 4,
      showScrollObserver: true
    }
  },
  created () {
    this.fetchPhotos(1, this.length)
      .then(() => {
        this.initIntersectionObserver()
      })
    // For next photo
    this.increasePhotoLength()
  },
  methods: {
    /**
     * @summary 사진을 κ°€μ Έμ˜΅λ‹ˆλ‹€.
     * @param {number} start - κ°€μ Έμ˜¬ μ‚¬μ§„μ˜ μ‹œμž‘ 포인트
     * @param {number} limit - κ°€μ Έμ˜¬ μ‚¬μ§„μ˜ 개수
     * @return {Promise} - 비동기 싀행을 μœ„ν•œ Promise 객체
     */
    fetchPhotos (start = 1, limit = 1) {
      return new Promise(resolve => {
        const photosToFetch = []
        for (let i = start; i < start + limit; i += 1) {
          photosToFetch.push(
            axios(`https://jsonplaceholder.typicode.com/photos/${i}`)
          )
        }
        
        Promise.all(photosToFetch)
          .then(photos => {
            return photos.map(photo => {
              return {
                ...photo.data,
                imageLoaded: false
              }
            })
          })
          .then(photos => {
            this.photos.push(...photos)
            this.photos.forEach(photo => {
              // 사진 λ‘œλ“œλ₯Ό λŒ€κΈ°
              const image = new Image()
              image.src = photo.url
              image.onload = () => {
                photo.imageLoaded = true
              }
            })
            resolve(true)
          })
      })
    },
    /**
     * @summary Intersection Observerλ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
     */
    initIntersectionObserver () {
      const io = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
          // μš”μ†Œ(#scroll-observer)의 κ°€μ‹œμ„±μ΄ ν™•λ³΄λ˜λ©΄..
          if (entry.isIntersecting) {
            this.fetchPhotos(this.length)
            // For next photo
            this.increasePhotoLength()
          }
        })
      }, {
        // 'Codepen'와 'JSFiddle'μ—μ„œλŠ” μ˜΅μ…˜μ΄ μ œλŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•ŠλŠ”κ΅°μš”.
        // μ˜΅μ…˜μ— λŒ€ν•œ ν…ŒμŠ€νŠΈλŠ” 'JSBin'μ΄λ‚˜ λ‘œμ»¬μ—μ„œ μ§„ν–‰ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.
        
        // λ‘œλ”© μ• λ‹ˆλ©”μ΄μ…˜μ΄ 보이지 μ•Šκ²Œ κ°€μ Έμ˜€κΈ°λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ„λ‘..
        // rootMargin: '0px 0px 400px 0px'
      })
      
      io.observe(this.$refs.scrollObserver)
    },
    /**
     * @summary κ°€μ Έμ˜¬ μ‚¬μ§„μ˜ μ‹œμž‘ 포인트λ₯Ό μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€.
     */
    increasePhotoLength () {
      this.length += 1
      console.log(this.length)
    }
  }
})