JS implementation of bottom touching event in rolling area

Keywords: Javascript Vue

Effect

Paste the effect display:

Implementation ideas

In terms of style, we don't need to elaborate. The scrolling area is set to a fixed height. Set overflow-y: auto to achieve this.

Next let's look at the implementation of js, which is also very simple. The trigger condition is: visible height + rolling distance > = actual height. I will use vue to implement the example, just like the native implementation.

  • Offset height: obtained through the offset height of dom, indicating the fixed height of the region. Here I recommend getBoundingClientRect() to get height, because using the former will cause browser reflow and some performance problems.
  • Scrolltop: obtained through e.target.scrollTop in the scrolling event, indicating the distance px between the scroll bar and the top
  • Actual height: obtained through the dom's scrollHeight, indicating the height of all contents in the area (including the rolling distance), that is, the actual height

Foundation realization

onScroll(e) {
    let scrollTop = e.target.scrollTop
    let scrollHeight = e.target.scrollHeight
    let offsetHeight = Math.ceil(e.target.getBoundingClientRect().height)
    let currentHeight = scrollTop + offsetHeight
    if (currentHeight >= scrollHeight) {
        console.log('Touch bottom')
    }
}

so easy~

Add details

Add some details. Now we hope to trigger the event a certain distance from the bottom, rather than wait until the bottom is completely reached. If you've done an applet, it's about the same as onreach button.

Declare a distance variable from the bottom

At this time, the triggering condition: visual height + rolling distance + reach bottomdistance > = actual height

export default {
  data(){
    return {
      reachBottomDistance: 100
    }
  },
  methods: {
    onScroll(e) {
        let scrollTop = e.target.scrollTop
        let scrollHeight = e.target.scrollHeight
        let offsetHeight = Math.ceil(e.target.getBoundingClientRect().height)
        let currentHeight = scrollTop + offsetHeight + this.reachBottomDistance
        if (currentHeight >= scrollHeight) {
            console.log('Touch bottom')
        }
    }
  }
}

The event is triggered successfully when it is 100px from the bottom, but because the area below 100px is qualified, it will trigger all the time, which is not what we want.

Next, do some processing to make it trigger only once after entering:

export default {
  data(){
    return {
      isReachBottom: false,
      reachBottomDistance: 100
    }
  },
  methods: {
    onScroll(e) {
        let scrollTop = e.target.scrollTop
        let scrollHeight = e.target.scrollHeight
        let offsetHeight = Math.ceil(e.target.getBoundingClientRect().height)
        let currentHeight = scrollTop + offsetHeight + this.reachBottomDistance

        if(currentHeight < scrollHeight && this.isReachBottom){
          this.isReachBottom = false
        }
        if(this.isReachBottom){
          return
        }
        if (currentHeight >= scrollHeight) {
          this.isReachBottom = true
          console.log('Touch bottom')
        }
    }
  }
}

optimization

Getting location information in real time will slightly degrade performance. We should cache the unchanged information and only get the variable part in real time

export default {
  data(){
    return {
      isReachBottom: false,
      reachBottomDistance: 100
      scrollHeight: 0,
      offsetHeight: 0,
    }
  },
  mounted(){
    // Store height after page loading
    let dom = document.querySelector('.comment-area .comment-list')
    this.scrollHeight = dom.scrollHeight
    this.offsetHeight = Math.ceil(dom.getBoundingClientRect().height)
  },
  methods: {
    onScroll(e) {
        let scrollTop = e.target.scrollTop
        let currentHeight = scrollTop + this.offsetHeight + this.reachBottomDistance

        if(currentHeight < this.scrollHeight && this.isReachBottom){
          this.isReachBottom = false
        }
        if(this.isReachBottom){
          return
        }
        if (currentHeight >= this.scrollHeight) {
          this.isReachBottom = true
          console.log('Touch bottom')
        }
    }
  }
}

If you have a better idea and something to improve, welcome to exchange~

Posted by gilang4 on Sat, 21 Mar 2020 02:44:40 -0700