转行小白历险记-2023/12/16 滚动提示栏组件开发+倒计时组件

  • uselnterval & useTimeout
  • ref 获取 DOM
  • withDefaults 设置 props 默认值
  • <style> 使用 <script setup> 里的 JS 变量
  • v-html渲染html模板
  • tansform: scale 实现小于 1px 的边线
  • ScrollBar 轮播组件的实现原理

需求分析

 

 1.使用 defineProps 函数和 withDefaults 函数

  • 你使用 defineProps 函数和 withDefaults 函数来定义和设置默认值。defineProps<IProps>() 创建了一个 IProps 类型的 props 对象,withDefaults 函数设置了 intervalTimetransitionTime 和 height 的默认值
interface IProps {
  intervalTime?: number
  transitionTime?: number
  height?: number
  data: IScrollBarInfo[]
}
const props = withDefaults(defineProps<IProps>(), {
  intervalTime: 3000,
  transitionTime: 1000,
  height: 40
})

二.自定义hooks-useCountDown实现倒计时逻辑

  • 使用 requestAnimationFrame(或 setTimeout) 计时
  • useCountDown 的设计
  • 性能优化:毫秒级/非毫秒级更新

01为什么要使用 requestAnimationFrame?

  1. 与浏览器的刷新率同步

    • requestAnimationFrame 会将动画函数与浏览器的刷新率同步。这意味着它会在每次屏幕重绘之前执行一次,通常是每秒60次(60Hz)。这有助于创建平滑的动画效果,因为它避免了动画帧和屏幕刷新之间的不一致。
  2. 性能优化

    • 浏览器可以对使用requestAnimationFrame的动画进行优化,比如在页面未激活或标签页不可见时减少或暂停动画,从而降低能耗和提高性能。
  3. 减少界面重排和重绘

    • 由于requestAnimationFrame是与浏览器的绘制过程同步的,它可以减少不必要的DOM操作和界面重绘,从而提高性能。

02为什么 setlnterval/setTimeout 不准?

  • 1时间延迟不精确

    • setTimeoutsetInterval指定的是最小延迟时间,并不保证精确执行。实际调用的时间可能会由于浏览器的任务调度或其他正在运行的脚本而延迟。
  • 2不与浏览器的刷新率同步

    • 这两种方法不考虑浏览器的绘制过程。因此,使用它们创建的动画可能与浏览器的帧率不同步,导致动画不流畅或出现“跳帧”现象。
  • 3效率问题

    • 在快速或高性能的动画中,setIntervalsetTimeout 可能导致性能问题,因为它们不能智能地调整动画帧率或在页面不可见时暂停动画。

2useCountDown需求分析

  • start 方法:开始计时
  • pause 方法:暂停计时
  • reset 方法:重置时间
  • current 变量:当前时间
  • 大量减少页面渲染的事件
    • 性能优化:是否需要毫秒级的计时
    • 当前剩余时间 currentRemain 是否与remain 为同一秒
    • 具体做法

03性能优化:毫秒级/非毫秒级更新是怎么做的

在提供的 useCountDown 钩子代码中,性能优化主要体现在根据用户需求选择毫秒级或非毫秒级更新。这是通过两种不同的定时循环函数 microTickmacroTick 来实现的。让我们来看看这两个函数是如何根据不同的需求进行优化的:

1. 毫秒级更新(microTick

在毫秒级更新中,倒计时需要在每一帧都进行更新。这种方式在显示毫秒数时非常有用,因为它可以提供非常平滑和精确的倒计时显示。

  • microTick 函数会在每次浏览器重绘之前执行一次,即每一帧都会更新。
  • 通过 requestAnimationFramerAF)递归调用自己,它确保倒计时的更新与浏览器的帧率同步,这对于渲染流畅的动画非常重要。
  • 这种方法在性能上是有效的,因为 requestAnimationFrame 通常是浏览器优化动画和重绘的首选方式。
2. 非毫秒级更新(macroTick

非毫秒级更新适用于不需要显示毫秒数的场景。在这种模式下,更新频率降低,只有当剩余时间的秒数发生变化时才进行更新。

  • macroTick 函数使用 requestAnimationFrame 递归调用自己,但不是在每一帧都更新倒计时。
  • 它检查当前剩余时间与上一次剩余时间是否处于同一秒。如果是同一秒,则不更新;只有当进入下一秒时才更新,这通过 isSameSecond 函数检查实现。
  • 这种方法减少了更新的频率,降低了对性能的影响,特别是当倒计时组件不需要展示毫秒数时。
总结

性能优化的关键在于根据需求选择合适的更新频率。毫秒级更新提供了更高的精确度和平滑度,适合动态和高精度的显示需求。非毫秒级更新则在不需要高频率更新时降低了性能消耗,提高了效率。通过这种方式,useCountDown 钩子能够根据具体的使用场景灵活地调整其性能和精确度

04useCountDown 倒计时钩子的逻辑

基于几个关键目标:提供一个灵活的倒计时功能,支持毫秒级更新,能够处理倒计时的开始、暂停、重置,以及在倒计时过程中触发特定的回调。以下是这段代码的核心逻辑:

1. 定义数据结构和类型
  • 类型定义CurrentTimeUseCountDownOptions 类型用于定义倒计时的数据结构和钩子的配置选项。
  • 时间单位常量:定义了秒、分钟、小时和天的毫秒值,以便于后续的时间计算。
2. 辅助函数
  • parseTime 函数:将给定的时间(毫秒)解析为天、小时、分钟、秒和毫秒的组合。
  • isSameSecond 函数:判断两个时间值是否处于同一秒内,用于非毫秒级更新的优化。
3. 主要逻辑
  • 初始化状态:使用 Vue 的 ref 创建响应式变量 remain 来存储剩余时间,以及使用 computed 创建计算属性 current 来实时解析剩余时间的结构。
  • 暂停和重置pause 函数用于停止倒计时,reset 函数用于重置倒计时。
  • 倒计时更新microTickmacroTick 函数使用 requestAnimationFrame 来递归地更新倒计时。microTick 用于毫秒级更新,而 macroTick 用于秒级更新。
  • 开始倒计时start 函数设置了倒计时的结束时间,并开始了更新循环。
4. 回调和剩余时间更新
  • 更新剩余时间setRemain 函数更新 remain 的值,并在每次更新时调用 onChange 回调(如果提供)。
  • 倒计时结束处理:当剩余时间为0时,setRemain 函数调用 onFinish 回调(如果提供)并停止倒计时。
5. 返回接口
  • 最后,钩子返回一个包含 startpauseresetcurrent 的对象,使得这些功能可以在组件中被访问和使用。
总体思考逻辑
  • 灵活性:钩子需要能够处理不同的倒计时需求,包括毫秒级的精确度。
  • 性能:使用 requestAnimationFrame 优化动画性能,确保倒计时更新平滑且高效。
  • 可用性:提供开始、暂停和重置功能,使得倒计时可以在各种情景下灵活使用。
  • 响应性:确保倒计时的当前状态可以响应式地被Vue组件使用。
  • 事件驱动:在关键事件(如每次更新和倒计时完成)时提供回调函数的触发。
  • 26
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值