You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue 3中设置组件实例层面的非响应式数据?

Vue 3存储非响应式数据的正确方案

针对Vue 2的同类问题,常用解决方案是使用$options存储非响应式数据,但该方案在Vue 3中完全不适用,原因如下:

  1. Vue 3官方明确标注$options为只读属性,禁止写入
  2. $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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 22:27:04