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
- You need to introduce written WXS modules
<wxs module="module" src="./index.wxs"></wxs>
Copy the code
- 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