Vue中MarkDown文档渲染滚动问题

clearmind
13
2024-12-28

概述

开发过程中使用了nextTick作为每次更新滚动的API,结果导致实现效果上不够流畅丝滑,总是一卡一卡的,查询问题后改用浏览器自己的APIrequestAnimationFrame ,极大的优化滚动的流畅感


1. nextTick 的工作原理

定义

nextTick 是 Vue.js 提供的一个工具函数,用于在下一个 DOM 更新周期之后执行回调函数。

适用场景

  • 在 Vue 中,当你修改了响应式数据后,需要等待 DOM 更新完成后再执行某些操作。
  • 例如,在更新列表后,确保 DOM 已经渲染完毕,然后再执行滚动操作。

代码示例

import { nextTick } from 'vue';

const scrollToBottomByNextTick = () => {
    if (messagesContainer.value) {
        nextTick(() => {
            messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
        });
    }
};

局限性

  • nextTick 并不关心浏览器的渲染时机,它只是确保在 Vue 的更新周期之后执行回调。
  • 如果 DOM 更新后浏览器还没有进行重绘,直接操作 scrollTop 可能会导致性能问题,尤其是在频繁更新的场景中。

2. requestAnimationFrame 的工作原理

定义

requestAnimationFrame 是浏览器提供的一个 API,用于在下一次浏览器重绘之前执行回调函数。

适用场景

  • 需要与浏览器的渲染周期同步的操作,例如滚动、动画等。
  • 在频繁更新 DOM 的场景中,requestAnimationFrame 可以避免不必要的重绘和性能问题。

代码示例

const scrollToBottomByNextTick = () => {
    if (messagesContainer.value) {
        requestAnimationFrame(() => {
            messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
        });
    }
};

优势

  • 它会在浏览器的最佳时机执行回调,确保操作更加平滑和高效。
  • 特别适合需要与浏览器渲染同步的操作,比如滚动到页面底部。

3. 为什么 requestAnimationFramenextTick 更适合滚动操作?

滚动操作(如设置 scrollTop)是一个与浏览器渲染密切相关的操作。以下是 requestAnimationFrame 更适合的原因:

  1. 与浏览器渲染同步

    • requestAnimationFrame 会在浏览器下一次重绘之前执行回调,确保滚动操作与浏览器的渲染周期同步。
    • nextTick 只是确保在 Vue 的更新周期之后执行回调,并不关心浏览器的渲染时机。
  2. 避免不必要的重绘

    • 如果使用 nextTick,可能会在 DOM 更新后立即执行滚动操作,而此时浏览器可能还没有完成重绘,导致额外的性能开销。
    • requestAnimationFrame 会将这些操作集中到浏览器的渲染周期内,减少不必要的重绘。
  3. 更平滑的动画效果

    • 对于需要平滑滚动的场景(如聊天应用),requestAnimationFrame 可以确保滚动操作更加流畅,而 nextTick 可能会导致卡顿或不连贯的效果。

4. 结合使用 nextTickrequestAnimationFrame

在某些场景中,你可能需要先确保 Vue 的更新完成,然后再执行与浏览器渲染相关的操作。这时可以结合使用 nextTickrequestAnimationFrame

代码示例

import { nextTick } from 'vue';

const scrollToBottom = () => {
    if (messagesContainer.value) {
        nextTick(() => {
            requestAnimationFrame(() => {
                messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
            });
        });
    }
};

流程

  1. nextTick 确保 Vue 的 DOM 更新完成。
  2. requestAnimationFrame 确保滚动操作在浏览器的最佳时机执行。

5. 总结

nextTick

  • 适合场景:在 Vue 的更新周期之后执行操作,但不关心浏览器的渲染时机。
  • 示例:确保 DOM 更新完成后再执行某些操作。

requestAnimationFrame

  • 适合场景:与浏览器渲染同步的操作,如滚动、动画等,能提供更好的性能和流畅度。
  • 示例:滚动到页面底部、动画效果等。

选择

  • 如果你的操作与浏览器渲染密切相关(如滚动),优先使用 requestAnimationFrame
  • 如果需要确保 Vue 的更新完成,可以结合使用 nextTickrequestAnimationFrame

6. 参考文档


动物装饰