微信公众号开发

小程序监听滚动时,更优雅的修改页面样式

本文主要是介绍小程序监听滚动时,更优雅的修改页面样式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

场景

在项目中有一个需求,监听页面滚动,动态修改组件的背景色,之前是在监听以后,计算颜色,通过

this.setData({
    bgColor: newBgColor
})
复制代码

方式修改背景色,但是在快速滚动情况下,会疯狂修改,一直调用setData()方法,性能很糟糕,会出现卡顿情况

核心就是减少setData()方法调用

解决思路

方案1

可以使用函数节流,防止调用太多,减少调用频率

方案2

具体分析,我们只是单纯的修改样式,不涉及逻辑,可以将修改的样式的动作放到渲染层去处理,不在通过逻辑层,直接将setData()次数减低到零

  • 要点
  • 小程序的运行环境分成渲染层和逻辑层
  • 在渲染层,可以监听事件,修改元素的样式

实现

方案1

定义一个函数节流工具

/**
 * @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;
}
复制代码

演示效果 TODO

方案2

定义wxs, 用于修改元素的样式

// 调用次数
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
  }
})
复制代码

页面渲染层

  1. 需要引入写好的wxs模块
<wxs module="module" src="./index.wxs"></wxs>
复制代码
  1. 监听滚动事件,在里面直接修改元素样式
<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;
}
复制代码
这篇关于小程序监听滚动时,更优雅的修改页面样式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!