如何在Vue 3中设置组件实例层面的非响应式数据?
Vue 3存储非响应式数据的正确方案
针对Vue 2的同类问题,常用解决方案是使用
$options存储非响应式数据,但该方案在Vue 3中完全不适用,原因如下:
- Vue 3官方明确标注
$options为只读属性,禁止写入$options本质是组件配置对象的公共引用,所有同类型组件实例共享该对象,写入后会被所有实例覆盖,才会出现所有tooltip都展示最后一个实例内容的问题
针对你当前使用的选项式API场景,最简便的方案如下:
方案1:直接挂载到组件实例(选项式API适用)
Vue 3的选项式API中,只有data函数返回的属性才会被处理为响应式,直接挂载到组件实例this上的自定义属性不会被做响应式代理,完全符合非响应式存储的需求。
修改后的代码:
<template> <i :class="['bi ', icon, hover && 'text-primary']" class="bg-body" @mouseover="hover = true; tooltip.show();" @mouseleave="hover = false; tooltip.hide();" @click="tooltip.hide();" style="cursor: pointer" :title="title" ref="icon" /> </template> <script> import {Tooltip} from "bootstrap"; export default { props: ["icon", "title"], data() { return { hover: false } }, mounted() { // 直接挂载到实例,非响应式,每个实例私有 this.tooltip = new Tooltip(this.$refs.icon,{ placement: 'bottom', trigger: 'manual', title: this.title || '' }); }, // 可选:组件销毁前清理tooltip实例,避免内存泄漏 beforeUnmount() { this.tooltip?.dispose() } } </script>
方案2:组合式API场景适用
如果使用组合式API,可以用shallowRef存储第三方实例,它不会递归代理内部属性,几乎没有额外性能开销:
import { shallowRef, ref, onMounted, onBeforeUnmount } from 'vue' import { Tooltip } from 'bootstrap' const icon = ref(null) // shallowRef包裹的内容不会被递归响应式处理 const tooltip = shallowRef(null) onMounted(() => { tooltip.value = new Tooltip(icon.value, { placement: 'bottom', trigger: 'manual' }) }) onBeforeUnmount(() => { tooltip.value?.dispose() })
内容的提问来源于stack exchange,提问作者Anton Ovsyannikov
相关产品推荐
相关产品推荐

