文章目录

    • 概要
    • 整体介绍
    • vue 中dom操作推荐方案实例

概要

从Vue 3的核心机制出发,结合场景、应用与实例,系统化解析事件流、DOM更新、数据请求、DOM操作规范及组件库DOM操作的解决方案:

整体介绍

⚡️ 一、事件流处理机制

  1. 核心机制
    • 三个阶段:捕获(从根节点向目标传递) → 目标(触发目标元素) → 冒泡(从目标向根节点回溯)。

    • Vue封装:默认在冒泡阶段处理事件,可通过 .capture 修饰符切换至捕获阶段。

  2. 应用场景与实例
    • 阻止冒泡:使用 @click.stop 替代原生 event.stopPropagation()。

 <div @click="parentClick"><button @click.stop="childClick">点击不触发父级</button></div>

• 事件委托优化:在父级监听子组件事件,通过 event.target 过滤目标。

• 自定义事件:子组件 $emit(‘update’, data),父组件 @update=“handler” 实现跨组件通信。

🔄 二、DOM更新原则

  1. 响应式驱动更新
    • Proxy代理:数据变更 → 触发依赖追踪 → 重新渲染虚拟DOM → Diff算法比对 → 精准更新真实DOM。

    • 批量更新:多次数据修改合并为单次渲染(nextTick 机制)。

  2. 性能优化策略
    • Patch Flags标记:动态节点添加标志(如 CLASS、STYLE),仅更新变化的属性。

    • Key的作用:列表渲染时,key 帮助Diff算法识别节点身份,避免不必要的重建。

<li v-for="item in list" :key="item.id">{{ item.name }}</li>

📡 三、数据请求原则

  1. 最佳实践
    • 生命周期挂钩:在 onMounted 中发起请求,避免SSR兼容问题。

    • 响应式绑定:数据存储于 ref/reactive,自动触发视图更新。

const data = ref([]);onMounted(async () => {data.value = await axios.get('/api/data');});

• 防抖/节流:高频请求(如搜索框)使用 lodash.debounce 优化。

  1. 状态管理整合
    • Pinia/Vuex:跨组件共享请求数据,通过 actions 封装异步逻辑。

⚖️ 四、Vue的DOM操作 vs 直接DOM操作

方式 Vue推荐方式 直接操作DOM的风险
获取DOM ref 绑定模板引用:

document.querySelector 破坏组件封装性
修改属性 数据驱动::class=“{ active }” el.className = ‘active’ 绕过响应式系统
动态结构 v-if/v-for 控制渲染 innerHTML 可能导致XSS漏洞

典型影响:
• 响应式失效:直接修改DOM不会更新Vue数据状态,导致数据与视图不一致。

• 性能下降:手动DOM操作可能触发多次重绘,抵消虚拟DOM的批量更新优势。

🧩 五、组件库中DOM操作的解决方案

  1. 问题根源
    组件库(如Element Plus)封装内部DOM结构,外部无法直接访问子组件DOM节点。

  2. 解决方案
    • Ref暴露:组件库通过 ref 暴露内部元素(需文档支持)

<el-input ref="inputRef" />  
setup() {  const inputRef = ref(null);  onMounted(() => inputRef.value?.focus());  
} 

• 插槽占位:使用插槽插入自定义内容并操作

 <el-dialog>  <div ref="dialogContent">自定义内容</div>  </el-dialog>

• 生命周期钩子:库组件提供 @opened 等事件,在适当时机操作DOM。

• Teleport组件:将内容渲染到外部容器(如全局弹窗),绕过组件层级。

💎 总结

Vue 3通过响应式驱动、虚拟DOM优化、事件系统封装构建高效开发范式。
• 规避直接DOM操作:优先使用数据驱动和 ref 接口。

• 组件库协作:善用暴露的API、插槽和生命周期事件,避免穿透组件边界。

• 性能关键:Diff算法与批量更新机制是高效渲染的核心,理解其原理可避免性能陷阱。

vue 中dom操作推荐方案实例

在 Vue 3 中监听 Ant Design Vue(AntDV)的 Table 组件滚动事件时,应优先使用 Vue 的响应式 API 和组件实例引用(ref)而非直接操作原生 DOM。以下是几种推荐方案及其实现方法:

🔍 1. 通过 ref 获取组件实例,再定位内部 DOM

原理:通过 ref 获取 Table 组件实例,再通过其 $el 属性访问根 DOM 元素,进一步用 querySelector 定位滚动容器(如 .ant-table-body)。
适用场景:需精确监听滚动容器(如表体)的滚动事件。
实现步骤:

<template><a-table ref="tableRef" :data-source="data" :columns="columns" /></template><script setup>import { ref, onMounted, onBeforeUnmount } from 'vue';const tableRef = ref(null);let scrollContainer = null;const handleScroll = (e) => {console.log('滚动位置:', e.target.scrollTop);};onMounted(() => {if (tableRef.value) {// 获取 Table 内部的滚动容器scrollContainer = tableRef.value.$el.querySelector('.ant-table-body');if (scrollContainer) {scrollContainer.addEventListener('scroll', handleScroll);}}});onBeforeUnmount(() => {if (scrollContainer) {scrollContainer.removeEventListener('scroll', handleScroll);}});</script>

注意:
• 需手动管理事件监听器的绑定与销毁,避免内存泄漏。

• AntDV 的滚动容器类名(如 .ant-table-body)可能随版本变化,需验证兼容性。

🎯 2. 直接使用 Table 组件的 @scroll 事件

原理:部分组件库为 Table 内置了 scroll 事件(需查阅文档确认支持性)。
适用场景:组件库已封装滚动事件时,代码更简洁。
实现步骤:

   <template><a-table @scroll="handleScroll" :data-source="data" :columns="columns" /></template><script setup>const handleScroll = (e) => {// e.target 为触发滚动的 DOM 元素console.log('滚动事件:', e);};</script>

注意:
• AntDV 官方文档未明确说明 @scroll 事件支持,实际测试发现部分版本可能生效。

• 若事件未触发,需回退到方案 1。

⚙️ 3. 结合 ref 与生命周期钩子优化

增强点:利用 nextTick 确保 DOM 渲染完成后再操作。
适用场景:动态数据加载后需操作滚动条(如滚动到底部)。
实现步骤:

<script setup>
import { nextTick } from 'vue';// 数据加载后滚动到底部const loadData = async () => {data.value = await fetchData();nextTick(() => {const container = tableRef.value?.$el.querySelector('.ant-table-body');if (container) {container.scrollTop = container.scrollHeight;}});};</script>

💎 方案对比与选择建议

方案 优点 缺点 适用场景

ref + 查询内部 DOM 精准控制滚动容器,兼容性强 需手动管理事件,依赖内部类名 需监听具体滚动容器

组件内置 @scroll 事件 代码简洁,符合 Vue 事件绑定规范 依赖组件库支持,可能不稳定 快速实现,兼容版本可用时

生命周期钩子优化 确保 DOM 更新后操作,避免空引用 需结合其他方案使用 动态数据加载后滚动定位

⚠️ 关键注意事项

  1. 避免直接操作 DOM
    Vue 的响应式设计优先通过数据驱动视图,直接操作 DOM(如 document.querySelector)会破坏封装性,导致与 Vue 的更新机制冲突。

  2. 组件库的封装限制
    AntDV 等组件库的内部 DOM 结构是黑盒,更新版本可能调整类名或结构。若必须操作内部 DOM,需在代码中增加兼容性处理。

  3. 使用 defineExpose 暴露子组件方法
    若需调用 Table 组件的内部方法(如滚动到指定行),可要求子组件通过 defineExpose 暴露方法,父组件通过 ref 调用:

   <!-- 子组件 --><script setup>defineExpose({ scrollToRow: (index) => { ... } });</script><!-- 父组件 --><script setup>const tableRef = ref(null);tableRef.value?.scrollToRow(10);</script>

💎 总结

优先使用 Vue 的 ref 获取组件实例,再通过其 $el 定位滚动容器,是平衡 Vue 响应式原则 与 操作 DOM 需求 的最佳实践。若组件库支持内置事件(如 @scroll),可进一步简化代码。务必在生命周期钩子中管理事件监听,并避免直接操作原生 DOM 以维护应用稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89140.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89140.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/89140.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python从入门到高手9.2节-Python字典的操作方法

目录 9.2.1 字典的操作 9.2.2 字典的查找 9.2.3 字典的修改 9.2.4 字典的添加 9.2.5 字典的删除 9.2.6 今天你逛街了吗 9.2.1 字典的操作 字典类型是一种抽象数据类型&#xff0c;抽象数据类型定义了数据类型的操作方法&#xff0c;在本节的内容中&#xff0c;教同学们彻…

omniparser v2 本地部署及制作docker镜像(20250715)

关于 omniparser v2 本地部署&#xff0c;网上资料不算多&#xff0c;尤其是对于土蔷内用户&#xff0c;还是有些坑的。 1、安装步骤 可参考两个CSDN博客&#xff1a; &#xff08;1&#xff09;大模型实战 - ‘OmniParser-V2本地部署安装 链接 &#xff08;2&#xff09;…

自己写个 `rsync` + `fswatch` 实时增量同步脚本,干掉 Cursor AI、Sublime Text 的SFTP等 插件!

自己写个 rsync fswatch 实时增量同步脚本&#xff0c;干掉 Cursor AI、Sublime Text 的 SFTP等 插件&#xff01; 作为一个码农&#xff0c;我最头疼的事情之一就是编辑器同步代码到服务器这块。用过各种各样的sftp、rsync插件&#xff0c;感觉不好用。。 我琢磨着&#xff1…

linux中at命令的常用用法。

Linux 中 at 命令用于安排一次性定时任务&#xff0c;需要用到在某个时间只需要执行一次的命令的时候&#xff0c;可以使用at 1&#xff1a;安装at # Debian/Ubuntu sudo apt install at# CentOS/RHEL sudo yum install at2&#xff1a;启动at sudo systemctl start atd # 启…

【安卓笔记】RxJava的使用+修改功能+搭配retrofit+RxView防快速点击

0. 环境&#xff1a; 电脑&#xff1a;Windows10 Android Studio: 2024.3.2 编程语言: Java Gradle version&#xff1a;8.11.1 Compile Sdk Version&#xff1a;35 Java 版本&#xff1a;Java11 1. 介绍RxJava GitHub开源地址&#xff1a;https://github.com/Reactive…

Windows 下原生使用 claude code + Kimi K2

搞定了kimi k2 claude code在windows下原生使用 Windows下使用claude code的障碍是shell环境&#xff08;命令行&#xff09;&#xff0c;非posix风格shell无法正常让claude code读取到url和key, 导致无法使用。解决问题的本质是使用符合posix风格的shell环境&#xff0c;我们…

Leetcode Easy题小解(C++语言描述)1

Leetcode Easy题小解&#xff08;C语言描述&#xff09; 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交**&#xff1a;**题目数据…

EP01:【NLP 第二弹】自然语言处理概述

一、NLP通向智能之路 1.1 图灵测试 1.1.1 提出背景 由计算机科学家阿兰・图灵于 1950 年提出&#xff0c;是早期衡量机器智能水平的重要概念。 1.1.2 提出目的 判断机器是否能表现出与人类相当的智能行为。 1.1.3 测试原理 场景设定&#xff1a;测试中存在一位人类测试者&#…

Ansible 查看PostgreSQL的版本

Ansible的基础知识就不说了直接贴剧本- name: Check PostgreSQL versionhosts: db_serversbecome: yesvars:ansible_python_interpreter: /usr/bin/python3db_name: postgresdb_user: postgresdb_password: your_passwordtasks:- name: Install psycopg2ansible.builtin.packag…

【视觉SLAM笔记】第9章 后端1

一、理论1. 状态估计的概率解释我们来深入探讨一下视觉SLAM中状态估计的概率解释。这可以说是理解现代SLAM算法&#xff08;尤其是后端优化&#xff09;的基石1. 问题的核心&#xff1a;不确定性SLAM&#xff08;同步定位与建图&#xff09;的本质是在一个未知环境中&#xff0…

(数据结构)复杂度

基本概念说明 数据结构 定义&#xff1a;数据结构(Data Structure)是计算机存储、组织数据的方式&#xff0c;指相互之间存在⼀种或多种特定关系的数据元素的集合。没有⼀种单⼀的数据结构对所有用途都有用&#xff08;要考虑适配、效率问题&#xff0c;在不同情况下使用合适的…

玩转Docker | 使用Docker部署bender个人导航页工具

玩转Docker | 使用Docker部署bender个人导航页工具 前言 一、bender介绍 Bender 简介 Bender 的主要特点 二、系统要求 环境要求 环境检查 Docker版本检查 检查操作系统版本 三、部署bender服务 下载bender镜像 编辑部署文件 创建容器 检查容器状态 检查服务端口 安全设置 四、…

解决了困扰我的upload靶场无法解析phtml等后缀的问题

本文章为解决困扰我的 upload 靶场无法解析 phtml 问题 ​ 这个问题直接让我过不了Upload-Pass-03这一关&#xff0c;一直卡着。 ​ 痛太痛了 &#xff0c;为什么无法解析上传之后的 phtml 后缀文件&#xff01;这块儿折磨了博主一天多&#xff0c;太不容易了&#xff0c;查找…

Leetcode百题斩-二分搜索

二分搜索也是一个很有趣的专题&#xff0c;被做过的题中&#xff0c;刚好一个Easy&#xff0c;一个Medium和一个Hard&#xff0c;刚好可以看看&#xff0c;二分搜索的三个难度等级都是啥样的。 124. Binary Tree Maximum Path Sum[Hard]&#xff08;详见二叉树专题&#xff09;…

【IDEA】格式化代码工具配置

格式化代码快捷键&#xff1a; CtrlAltL格式代码的时候不会再方法名与参数中间添加空格默认不勾选的情况下&#xff1a;代码样例&#xff1a;勾选之后的样例&#xff1a;选择不勾选&#xff0c;IDEA默认情况下就是不勾选的状态忽略加载文件有些非必要加载到开发工具中的文件我们…

驱动开发(3)|rk356x驱动GPIO基础应用之点亮led灯

点亮LED灯看似是一个基础的操作&#xff0c;但实际上&#xff0c;许多高级应用也依赖于高低电平的切换。例如&#xff0c;脉冲宽度调制&#xff08;PWM&#xff09;信号可以用来精确控制电机的转速&#xff0c;通过改变脉冲的频率和占空比&#xff0c;实现对电机的精确调节&…

手动搭建PHP环境:步步为营,解锁Web开发

目录一、引言二、准备工作2.1 明确所需软件2.2 下载软件三、Windows 系统搭建步骤3.1 安装 Apache 服务器3.2 安装 PHP3.3 集成 Apache 与 PHP3.4 安装 MySQL3.5 配置 PHP 连接 MySQL四、Linux 系统搭建步骤&#xff08;以 Ubuntu 为例&#xff09;4.1 更新系统4.2 安装 Apache…

DrissionPage:一款让网页自动化更简单的 Python 库

在网页自动化领域&#xff0c;Selenium 和 Playwright 早已是开发者耳熟能详的工具。但今天要给大家介绍一款更轻量、更易用的 Python 库 ——DrissionPage。它以 "融合 selenium 和 requests 优势" 为核心设计理念&#xff0c;既能像 requests 一样高效处理静态网页…

理解Grafana中`X-Scope-OrgID`的作用与配置

X-Scope-OrgID的作用 该HTTP Header用于标识Loki日志数据的所属租户&#xff08;组织&#xff09;。在多租户模式下&#xff0c;Loki通过此Header隔离不同团队或用户的数据&#xff0c;确保查询和存储的独立性。数据隔离&#xff1a; 租户A的日志标记为X-Scope-OrgID: team-a&a…

【PycharmPyqt designer桌面程序设计】

在 main.py 中调用 Qt Designer 生成的 windows.py&#xff08;假设它是 PySide2 版&#xff09;。 只要把两个文件放在同一目录即可直接运行。 ──────────────────── 1️⃣ windows.py&#xff08;Qt Designer 生成&#xff0c;已转码&#xff09; # -*-…