在项目中有一个需求,监听页面滚动,动态修改组件的背景色,之前是在监听以后,计算颜色,通过
this.setData({ bgColor: newBgColor }) 复制代码
方式修改背景色,但是在快速滚动情况下,会疯狂修改,一直调用setData()
方法,性能很糟糕,会出现卡顿情况
核心就是减少setData()
方法调用
可以使用函数节流
,防止调用太多,减少调用频率
具体分析,我们只是单纯的修改样式,不涉及逻辑,可以将修改的样式的动作放到渲染层去处理,不在通过逻辑层,直接将setData()
次数减低到零
/** * @description 函数节流: 每隔一段时间,只执行一次函数 * @param { Function } fn 需要延迟执行的函数 * @param { Number } interval 延迟执行的时间,默认值500ms */ export function throttle(fn, interval = 500) { // 记录定时器id let timer = null // 是否是第一次调用 let isFirstTime = true return function () { const args = arguments const _me = this // 第一次直接执行,改变标志,无需延迟 if (isFirstTime) { fn.apply(_me, args) return (isFirstTime = false) } // 不是第一次 // 存在定时器,前面的延迟操作没有完成,直接返回,拒绝调用请求 if (timer) { return false } // 延迟执行 timer = setTimeout(() => { clearTimeout(timer) timer = null fn.apply(_me, args) }, interval) } } 复制代码
// index.js import { throttle } from '../utils/util'; // 创建一个长度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 let channelColor = top * 1 // 任意通道颜色 if(channelColor > 255) { channelColor = channelColor%255 } // 样式 const style = `background-color: rgb(${channelColor}, ${channelColor},${channelColor});` this.setData({ style // 设置背景色 }, () => { this.countStatistics() }) }, 300), // 调用次数 count: 0, // 更新调用次数和并打印出来 countStatistics() { ++this.count console.log(this.count) } }) 复制代码
<!-- index.html --> <!-- 一个大盒子包住所有的元素 --> <view class="container-fill"> <!-- 包住 swiper 组件 --> <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> 复制代码
/* 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%; transition: all 0.3s; } .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; } 复制代码
// 调用次数 var count = 0 function handleScroll(e, ownerInstance) { var top = e.detail.scrollTop var channelColor = top * 1 // 任意通道颜色 if (channelColor > 255) { channelColor = channelColor % 255 } var instances = ownerInstance.selectAllComponents('.item') // 获取类名为item的组件 for(var i = 0; i < instances.length; i++) { var instance = instances[i] instance.setStyle({ 'background-color': 'rgb(' + channelColor + ',' + channelColor + ',' + channelColor + ')', // 设置背景色 }) } countStatistics() } // 更新调用次数和并打印出来 function countStatistics() { ++count console.log(count) } module.exports = { handleScroll: handleScroll } 复制代码
// 创建一个长度100的数组 const list = [...new Array(100).keys()].map(i => { return { name: 'lisr' + (i + 1), age: i + 1} }) Page({ data: { list: list } }) 复制代码
<wxs module="module" src="./index.wxs"></wxs> 复制代码
<scroll-view scroll-y="true" style="height: 100%;" bindscroll="{{module.handleScroll}}"> 复制代码
注意引入模块使用{{}}
包裹
完整代码如下:
<!-- index.html --> <wxs module="module" src="./index.wxs"></wxs> <!-- 一个大盒子包住所有的元素 --> <view class="container-fill"> <!-- 包住 swiper 组件 --> <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> 复制代码
/* 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%; transition: all 0.3s; } .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; } 复制代码