Vue 项目中使用$refs来访问组件实例或 DOM 元素,有哪些注意事项?

大白话Vue 项目中使用$refs来访问组件实例或 DOM 元素,有哪些注意事项?

在 Vue 项目里,$refs 是个超实用的工具,它能让你直接访问组件实例或者 DOM 元素。不过使用的时候,有一些地方可得注意,下面咱就详细唠唠。

1. $refs 只有在组件渲染完成后才可用

在 Vue 里,组件从创建到渲染完成是有个过程的。只有当组件完全渲染好了,$refs 才能正常使用。要是在组件还没渲染好的时候就想用 $refs 去访问东西,那肯定会出问题。所以,通常会把使用 $refs 的代码放到 mounted 钩子函数里,因为这个钩子函数是在组件渲染完成后才执行的。

export default {// 组件挂载完成后执行的钩子函数mounted() {// 这里可以安全地使用 $refs 访问组件实例或 DOM 元素this.$refs.myComponent.someMethod(); // 调用组件实例的方法this.$refs.myElement.focus(); // 让 DOM 元素获取焦点}
};

2. 不要在模板里直接使用 $refs

虽然 $refs 能让你访问组件实例或者 DOM 元素,但千万别在模板里直接用它。因为模板里的代码会在每次数据更新的时候重新计算,如果在模板里用 $refs,可能会导致意外的结果,而且还会影响性能。

<template><!-- 不要这样做 --><!-- <div>{{ $refs.myElement.textContent }}</div> --><div ref="myElement">这是一个 DOM 元素</div>
</template><script>
export default {mounted() {// 在 mounted 钩子函数里使用 $refsconst text = this.$refs.myElement.textContent;console.log(text); // 输出: 这是一个 DOM 元素}
};
</script>

3. $refs 不是响应式的

$refs 不像 Vue 的响应式数据那样,数据一变页面就跟着更新。$refs 只是一个普通的对象,它的属性值在组件渲染完成后就固定了。所以,如果你想在数据变化的时候更新 $refs 相关的操作,就得手动去处理。

<template><div><button @click="updateElement">更新元素</button><div ref="myElement">{{ message }}</div></div>
</template><script>
export default {data() {return {message: '初始消息'};},methods: {updateElement() {this.message = '更新后的消息';// 手动更新 $refs 相关的操作this.$refs.myElement.textContent = this.message;}}
};
</script>

4. 动态绑定 ref 时要注意

要是你需要动态绑定 ref,也就是根据不同的条件给不同的元素或者组件绑定 ref,那得小心了。因为动态绑定 ref 可能会导致 $refs 的值发生变化,所以在使用的时候要确保 $refs 里确实有你想要的元素或者组件。

<template><div><!-- 动态绑定 ref --><component :is="currentComponent" :ref="currentRef"></component><button @click="switchComponent">切换组件</button></div>
</template><script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';export default {data() {return {currentComponent: ComponentA,currentRef: 'componentRef',componentRef: null};},methods: {switchComponent() {this.currentComponent = this.currentComponent === ComponentA ? ComponentB : ComponentA;// 切换组件后,确保 $refs 里有正确的组件实例if (this.$refs.componentRef) {this.$refs.componentRef.someMethod();}}}
};
</script>

5. 在子组件销毁时清理 $refs

当子组件被销毁的时候,$refs 里对应的引用不会自动清除。所以,要是你在子组件销毁后还去访问 $refs 里的这个引用,就会报错。为了避免这种情况,你可以在子组件销毁的时候手动清理 $refs 里的引用。

<template><div><child-component ref="childRef"></child-component><button @click="destroyChild">销毁子组件</button></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},methods: {destroyChild() {// 销毁子组件this.$refs.childRef.$destroy();// 手动清理 $refs 里的引用this.$refs.childRef = null;}}
};
</script>

总之,$refs 是个很强大的工具,但使用的时候得注意上面这些点,这样才能避免出现各种奇怪的问题,让你的 Vue 项目更加稳定。

除了$refs,Vue还有哪些可以访问组件实例或DOM元素的方式?

在 Vue 里,除了使用 $refs 访问组件实例或 DOM 元素外,还有以下几种方式:

1. 通过事件机制传递信息

在 Vue 中,你可以利用自定义事件和事件总线在组件间传递数据,从而间接访问组件实例。

自定义事件

子组件能够通过 $emit 触发自定义事件,把数据传递给父组件,父组件在接收到事件后就可以访问子组件实例的属性或方法。

<template><!-- 父组件 --><div><child-component @custom-event="handleCustomEvent"></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},methods: {handleCustomEvent(childInstance) {// 访问子组件实例console.log(childInstance.someMethod());}}
};
</script>
<template><!-- 子组件 --><div><button @click="sendInstance">发送实例</button></div>
</template><script>
export default {methods: {sendInstance() {// 触发自定义事件,传递当前组件实例this.$emit('custom-event', this);},someMethod() {return '这是子组件的方法';}}
};
</script>
事件总线

事件总线是一个全局的事件中心,组件能够在上面触发和监听事件,以此实现组件间的通信。

// eventBus.js
import Vue from 'vue';
export const eventBus = new Vue();
<template><!-- 发送组件 --><div><button @click="sendMessage">发送消息</button></div>
</template><script>
import { eventBus } from './eventBus.js';export default {methods: {sendMessage() {// 触发事件总线的事件eventBus.$emit('message-sent', this);}}
};
</script>
<template><!-- 接收组件 --><div></div>
</template><script>
import { eventBus } from './eventBus.js';export default {mounted() {// 监听事件总线的事件eventBus.$on('message-sent', (senderInstance) => {console.log(senderInstance.someMethod());});}
};
</script>

2. 使用 provideinject

provideinject 主要用于实现跨级组件间的通信,父组件能够通过 provide 提供数据,子组件可以使用 inject 注入这些数据。

<template><!-- 父组件 --><div><child-component></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},provide() {return {parentInstance: this};}
};
</script>
<template><!-- 子组件 --><div></div>
</template><script>
export default {inject: ['parentInstance'],mounted() {// 访问父组件实例console.log(this.parentInstance.someMethod());}
};
</script>

3. 使用 Vue.observable(Vue 2)或 reactive(Vue 3)

在 Vue 2 里可以使用 Vue.observable 创建一个响应式对象,在 Vue 3 中则使用 reactive。通过这个响应式对象存储组件实例,从而实现对组件实例的访问。

Vue 2
// store.js
import Vue from 'vue';export const store = Vue.observable({componentInstance: null
});
<template><!-- 组件 A --><div><button @click="setInstance">设置实例</button></div>
</template><script>
import { store } from './store.js';export default {methods: {setInstance() {// 将当前组件实例存储到响应式对象中store.componentInstance = this;}}
};
</script>
<template><!-- 组件 B --><div></div>
</template><script>
import { store } from './store.js';export default {mounted() {// 访问存储的组件实例if (store.componentInstance) {console.log(store.componentInstance.someMethod());}}
};
</script>
Vue 3
// store.js
import { reactive } from 'vue';export const store = reactive({componentInstance: null
});
<template><!-- 组件 A --><div><button @click="setInstance">设置实例</button></div>
</template><script setup>
import { store } from './store.js';const setInstance = () => {// 将当前组件实例存储到响应式对象中store.componentInstance = getCurrentInstance();
};
</script>
<template><!-- 组件 B --><div></div>
</template><script setup>
import { store } from './store.js';if (store.componentInstance) {console.log(store.componentInstance.someMethod());
}
</script>

这些方法都有各自的适用场景,你可以根据具体需求来选择合适的方式。

在Vue中,如何避免$refs访问带来的性能问题?

在 Vue 里使用 $refs 访问组件实例或 DOM 元素时,若使用不当可能会引发性能问题。以下是一些避免 $refs 访问带来性能问题的方法:

1. 避免在渲染循环中频繁访问 $refs

$refs 本身并非响应式的,但在渲染循环里频繁访问 $refs 会导致不必要的计算和 DOM 操作,从而降低性能。应该把 $refs 的访问逻辑移到事件处理函数或者生命周期钩子函数中。

<template><div><div ref="myElement">示例元素</div><button @click="handleClick">点击</button></div>
</template><script>
export default {methods: {handleClick() {// 在事件处理函数中访问 $refsconst element = this.$refs.myElement;if (element) {// 对元素进行操作element.style.color = 'red';}}}
};
</script>

2. 仅在必要时使用 $refs

$refs 主要用于直接访问组件实例或 DOM 元素,不过很多时候可以借助 Vue 的响应式系统来实现相同的功能,从而避免使用 $refs

示例:动态改变样式

不使用 $refs 的情况:

<template><div><div :style="{ color: textColor }">示例元素</div><button @click="changeColor">改变颜色</button></div>
</template><script>
export default {data() {return {textColor: 'black'};},methods: {changeColor() {this.textColor = 'red';}}
};
</script>

3. 及时清理不再使用的 $refs

当组件被销毁时,$refs 里对应的引用不会自动清除。若不清理,可能会造成内存泄漏。所以在组件销毁时要手动清理 $refs

<template><div><child-component ref="childRef"></child-component><button @click="destroyChild">销毁子组件</button></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},methods: {destroyChild() {// 销毁子组件this.$refs.childRef.$destroy();// 手动清理 $refs 里的引用this.$refs.childRef = null;}}
};
</script>

4. 避免在 watch 中频繁访问 $refs

watch 用于监听数据变化,若在 watch 里频繁访问 $refs,会导致不必要的性能开销。可以在 watch 中设置 immediate: false,避免初始化时就执行访问操作。

<template><div><div ref="myElement">示例元素</div><input v-model="inputValue" /></div>
</template><script>
export default {data() {return {inputValue: ''};},watch: {inputValue: {handler(newValue) {if (this.$refs.myElement) {// 对元素进行操作this.$refs.myElement.textContent = newValue;}},immediate: false // 避免初始化时执行}}
};
</script>

5. 利用缓存机制

要是需要多次访问 $refs,可以把访问结果缓存起来,避免重复访问。

<template><div><div ref="myElement">示例元素</div><button @click="doSomething">执行操作</button><button @click="doAnotherThing">执行另一个操作</button></div>
</template><script>
export default {data() {return {cachedElement: null};},methods: {getElement() {if (!this.cachedElement) {this.cachedElement = this.$refs.myElement;}return this.cachedElement;},doSomething() {const element = this.getElement();if (element) {// 对元素进行操作element.style.fontSize = '20px';}},doAnotherThing() {const element = this.getElement();if (element) {// 对元素进行另一个操作element.style.backgroundColor = 'yellow';}}}
};
</script>

通过以上这些方法,可以有效避免 $refs 访问带来的性能问题,提升 Vue 应用的性能和稳定性。

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

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

相关文章

WEB或移动端常用交互元素及组件 | Axure / 元件类型介绍(表单元件、菜单和表格 、流程元件、标记元件)

文章目录 引言I Axure / 元件类型介绍基本元件表单元件菜单和表格流程元件标记元件II Axure 基础Axure / 常用功能介绍Axure / 常用元素实例Axure / 动态交互实例Axure / 常用设计分辨率推荐III Axure / 创建自己的元件库元件库作用元件库的创建及使用引言 I Axure / 元件类型介…

如何排查C++程序的CPU占用过高的问题

文章目录 可能的原因程序设计的BUG系统资源问题恶意软件硬件问题 通常步骤一个简单的问题代码在windows平台上如何排查Windows Process ExplorerWinDBG 在Linux平台如何排查使用TOP GDBPerf 可能的原因 程序设计的BUG 有死循环低效算法与数据结构滥用自旋锁频繁的系统调用&a…

19726 星际旅行

19726 星际旅行 ⭐️难度&#xff1a;困难 &#x1f31f;考点&#xff1a;Dijkstra、省赛、最短路问题、期望、2024 &#x1f4d6; &#x1f4da; import java.util.*;public class Main {static int N 1005;static ArrayList<Integer>[] g new ArrayList[N]; // …

vue3 + ant-design-vue4实现Select既可以当输入框也可以实现下拉选择

近日工作中&#xff0c;遇到一个需求&#xff0c;就是select的有一个前置切换条件&#xff0c;有些条件需要时输入&#xff0c;有些条件需要时下拉选择&#xff0c;但是在切换的时候&#xff0c;后面的这个输入或者选择组件不能闪烁&#xff0c;于是也就只能采用select去实现&a…

Unity UGUI - 六大基础组件

目录 一、Canvas上 1. Canvas&#xff1a;复制渲染子UI控件 2. ✨Canvas Scaler✨&#xff1a;画布分辨率自适应 3. Graphics Raycaster&#xff1a;射线事件响应 4. ✨Rect Transform✨&#xff1a;UI位置锚点对齐 二、Event System上 5. Event System 6. Standalone …

VSCode中使用Markdown以及Mermaid实现流程图和甘特图等效果

前言 Markdown&#xff08;简称md&#xff09;这种文件格式&#xff0c;渐渐盛行起来。有点类似html格式的意思。特别是内嵌的对Marmaid的支持&#xff0c;对流程图、甘特图等的绘制&#xff0c;都非常的方便。 一、安装Markdown的插件 二、创建.md文件 新建一个Markdown文件&…

如何让 history 记录命令执行时间?Linux/macOS 终端时间戳设置指南

引言:你真的会用 history 吗? 有没有遇到过这样的情况:你想回顾某个重要命令的执行记录,却发现 history 只列出了命令序号和内容,根本没有时间戳?这在运维排查、故障分析、甚至审计时都会带来极大的不便。 想象一下,你在服务器上误删了某个文件,但不知道具体是几点执…

css—— object-fit 属性

一&#xff0c;属性值 object-fit: fill | contain | cover | none | scale-down;原本的图片&#xff1a; 属性值效果&#xff1a; <!DOCTYPE html> <html> <head><style>.container {display: flex;flex-wrap: wrap;gap: 20px;}.box {width: 200px…

端游熊猫脚本游戏精灵助手2025游戏办公脚本工具!游戏脚本软件免费使用

在当下这个崇尚高效与便捷的时代&#xff0c;自动化工具已然成为诸多开发者与企业提升工作效率的关键选择。熊猫精灵脚本助手作为一款极具实力的自动化工具&#xff0c;凭借其多样的功能以及广泛的应用场景&#xff0c;逐步成为众多用户的首要之选。 熊猫精灵脚本助手整合了丰…

Docker安装MySql 8.0

1、验证环境 docker -v使用上面的命令检查一下本机的docker的运行环境。执行完成之后&#xff0c;会输出docker的版本号 我本地输出以下内容: Docker version 27.5.1, build 9f9e4052、拉取镜像 docker pull mysql:8.0拉取mysql8.0版本对的镜像。正常情况如下: 如果报下面的…

Jmeter-负载测试

目录 一. 基础负载测试场景&#xff1a;固定并发用户数 1、线程组配置 2、HTTP请求配置 3、添加定时器 4、添加监听器 4.1 聚合报告 4.2 响应时间图 4.3 查看结果树 5、结果分析指标 二. 阶梯式加压场景&#xff08;逐步增加并发&#xff09; 1、插件安装 2、阶梯配…

【新手初学】读取数据库数据

利用注入点让SQL注入语句执行读取数据库数据相关的操作&#xff01; 以下均以pikachu靶场的字符型注入为例进行介绍说明 一、读取用户名&#xff0c;数据库版本信息 在原URL后面添加如下代码&#xff1a; union select user(),version(&#xff09;-- 效果&#xff1a; 补…

Ubuntu与Windows之间相互复制粘贴的方法

一、打开Ubuntu终端 二、卸载已有的工具 sudo apt-get autoremove open-vm-tools 三、安装工具 sudo apt-get install open-vm-tools-desktop 四、重启 直接输入reboot 注&#xff1a;有任何问题欢迎评论区交流讨论或者私信&#xff01;

免去繁琐的手动埋点,Gin 框架可观测性最佳实践

作者&#xff1a;牧思 背景 在云原生时代的今天&#xff0c;Golang 编程语言越来越成为开发者们的首选&#xff0c;而对于 Golang 开发者来说&#xff0c;最著名的 Golang Web 框架莫过于 Gin [ 1] 框架了&#xff0c;Gin 框架作为 Golang 编程语言官方的推荐框架 [ 2] &…

【QT】新建QT工程(详细步骤)

新建QT工程 1.方法(1)点击new project按钮&#xff0c;弹出对话框&#xff0c;新建即可&#xff0c;步骤如下&#xff1a;(2) 点击文件菜单&#xff0c;选择新建文件或者工程&#xff0c;后续步骤如上 2.QT工程文件介绍(1).pro文件 --》QT工程配置文件(2)main.cpp --》QT工程主…

优化MyBatis-Plus批量插入策略

优化MyBatis-Plus批量插入策略 优化MyBatis-Plus批量插入策略一、用Mybatis-plus中的saveBatch方法二、InsertBatchSomeColumn插件1.使用前配置2.代码示例1.配置类 MybatisPlusConfig2).实体类 User3).Mapper 接口 UserMapper4).测试类 InsertBatchTest 优化MyBatis-Plus批量插…

记一次系统单点登录、模拟web系统登录方式的开发过程,使用AES加密

1.系统原始登录方式 访问登录页 输入账号密码登录后 2.从登录页找进去&#xff0c;从代码层面查看系统登录逻辑 常规登录方式为前端ajax请求LoginService服务-->返回200则跳转到home系统首页 查看LoginService登录逻辑 后台获取ajax传递的信息-->比较验证码-->查询…

iPhone mini,永远再见了

世界属于多数派&#xff0c;尽管有极少数人对 iPhone mini 情有独钟&#xff0c;但因为销量惨淡&#xff0c;iPhone mini 还是逃不开停产的命运。 据 Counterpoint 的数据&#xff0c;iPhone 12/13 mini 两代机型&#xff0c;仅占同期 iPhone 销量的 5%。 因为是小屏手机&…

监控易一体化运维:监控易机房管理,打造高效智能机房

在数字化浪潮中&#xff0c;企业对数据中心和机房的依赖程度与日俱增&#xff0c;机房的稳定运行成为业务持续开展的关键支撑。信息化的变迁&#xff0c;见证了机房管理从传统模式向智能化、精细化转变的过程。今天&#xff0c;就为大家深度剖析监控易在机房管理方面的卓越表现…

概率与决策理论

1.Q-learning Q-Learning 是一种无模型&#xff08;model-free&#xff09;强化学习算法&#xff0c;用于学习在马尔可夫决策过程&#xff08;MDP&#xff09;中的最优策略。它通过迭代更新 ​Q 值&#xff08;动作价值函数&#xff09;​ 来估计在某个状态下采取某个动作的长…