scenario

There is a requirement in the project to listen to the page scroll, dynamically modify the component’s background color, before it is after listening, calculate the color, through

this.setData({
    bgColor: newBgColor
})
Copy the code

Method to change the background color, but in the case of fast scrolling, it will frantically change, always call setData() method, performance is poor, there will be a stalling situation

The core is to reduce setData() method calls

solution

Plan 1

You can use function throttling to prevent too many calls and reduce the frequency of calls

Scheme 2

Specifically, we only modify the style without logic. We can put the action of the modified style into the rendering layer and directly reduce the setData() times to zero instead of through the logic layer

  • The main points of
  • The running environment of small program is divided into rendering layer and logic layer
  • In the render layer, you can listen for events and modify the style of elements

implementation

Plan 1

Define a function throttling tool

/** * @description function throttling: Function @param {Function} fn Function to be delayed * @param {Number} interval delay time. The default value is 500ms */export functionThrottle (fn, interval = 500) {// Record the timer IDletTimer = null // Whether it is the first calllet isFirstTime = true

  return function() {const args = arguments const _me = thisif (isFirstTime) {
      fn.apply(_me, args)
      return (isFirstTime = false} // This is not the first time // there is a timer, the previous delay operation did not complete, directly return, reject the call requestif (timer) {
      return false} // Delay execution of timer =setTimeout(() => {
      clearTimeout(timer)
      timer = null
      fn.apply(_me, args)
    }, interval)
  }
}
Copy the code

Use throttling functions in the page

// index.js
import { throttle } from '.. /utils/util'; // Create an Array of length 100 const list = [...new Array(100).keys()].map(I => {return { name: 'lisr' + (i + 1), age: i + 1}
})

Page({
  data: {
    list: list
  },

  onScroll: throttle(function(e) {
    console.log(e)
    const { scrollTop: top } = e.detail
    letChannelColor = top * 1 // any channelColorif(channelColor > 255) {channelColor = channelColor%255} const style = 'background-color: RGB (${channelColor}.${channelColor}.${channelColor}); 'this.setData({style // set background color}, () => {this.countStatistics()})}, 300), // Count: 0, // Update the number of calls and print them outcountStatistics() {
    ++this.count
    console.log(this.count)
  }
})
Copy the code

Page structure

<! -- index.html --> <! -- a big box that encloses all the elements --> <view class="container-fill"> <! -- Wrap swiper component --> <view class="scroll-fullpage" style="height: 100%">
        <scroll-view scroll-y="true" style="height: 100%;" bindscroll="onScroll">
            <view class="item" hover-class="none" hover-stop-propagation="false" style="{{style}}" wx:for="{{ list }}" wx:key="index">
                {{item.name}} - {{item.age}}
            </view>
        </scroll-view>
    </view>
</view>
Copy the code

The page style

/* index.wxss */ .container-fill { position: fixed; top: 0; bottom: 0; left: 0; right: 0; overflow: hidden; z-index: 10; } .container-fill .scroll-fullpage { height: 100%; The transition: all 0.3 s; } .scroll-fullpage .item { height: 30%; width: 80%; background-color: skyblue; border-radius: 10rpx; margin: 50rpx auto; display: flex; justify-content: center; align-items: center; font-size: 50rpx; }Copy the code

Demo effect TODO

Scheme 2

Defines WXS to modify the style of elements

Var count = 0functionHandleScroll (e, ownerInstance) {var top = e.daily. scrollTop var channelColor = top * 1 // any channelColorif (channelColor > 255) {
    channelColor = channelColor % 255
  }
  var instances = ownerInstance.selectAllComponents('.item'// Get the component of class itemfor(var i = 0; i < instances.length; i++) {
    var instance = instances[i]
    instance.setStyle({
      'background-color':
        'rgb(' + channelColor + ', ' + channelColor + ', ' + channelColor + ') ', // Set the background color})} countStatistics()} // Update the number of calls and print them outfunction countStatistics() {
  ++count
  console.log(count)
}

module.exports = {
  handleScroll: handleScroll
}
Copy the code

Page logic layer code

// Create an Array of length 100 const list = [...new Array(100).keys()].map(I => {return { name: 'lisr' + (i + 1), age: i + 1}
})

Page({
  data: {
    list: list
  }
})
Copy the code

Page rendering layer

  1. You need to introduce written WXS modules
<wxs module="module" src="./index.wxs"></wxs>
Copy the code
  1. Listen for the scroll event, where you modify the element style directly
<scroll-view scroll-y="true" style="height: 100%;" bindscroll="{{module.handleScroll}}">
Copy the code

Note that the import module is wrapped with {{}}

The complete code is as follows:

<! -- index.html --> <wxs module="module" src="./index.wxs"></wxs> <! -- a big box that encloses all the elements --> <view class="container-fill"> <! -- Wrap swiper component --> <view class="scroll-fullpage" style="height: 100%">
        <scroll-view scroll-y="true" style="height: 100%;" bindscroll="{{module.handleScroll}}">
            <view class="item" hover-class="none" hover-stop-propagation="false" style="{{style}}" wx:for="{{ list }}" wx:key="index">
                {{item.name}} - {{item.age}}
            </view>
        </scroll-view>
    </view>
</view>

Copy the code

The page style

/* index.wxss */ .container-fill { position: fixed; top: 0; bottom: 0; left: 0; right: 0; overflow: hidden; z-index: 10; } .container-fill .scroll-fullpage { height: 100%; The transition: all 0.3 s; } .scroll-fullpage .item { height: 30%; width: 80%; background-color: skyblue; border-radius: 10rpx; margin: 50rpx auto; display: flex; justify-content: center; align-items: center; font-size: 50rpx; }Copy the code