[vuejs/vue]Vue2.7 和 Vue3 使用 toRefs 时表现不同。

2025-10-29 701 views
2
版本

2.7.14

复制链接

codesandbox.io

重现步骤

Vue 2.7.14 CodeSandbox

https://codesandbox.io/s/recursing-tree-kfpd6x?file=/src/App.vue

Vue 3 CodeSandbox

https://codesandbox.io/s/charming-paper-b4u9qy?file=/src/App.vue

相同的代码。

在Vue 2.7.14 渲染结果

aHook.loading: { "value": false }

在Vue 3渲染结果

aHook.loading: true

<template>
  <div>
    <div>aHook.loading: {{ aHook.loading }}</div>
    <!-- vue 2.7.14: aHook.loading: { "value": false } -->
    <!-- vue 3: aHook.loading: true -->
    <div>loading:{{ loading }}</div>
    <button @click="clickBtn1">clickBtn1</button>
  </div>
</template>

<script>
import { defineComponent, reactive, toRefs } from 'vue';

export default defineComponent({
  setup() {
    function useAHook() {
      const state = reactive({
        loading: false,
      });
      return {
        ...toRefs(state),
        fn() {
          state.loading = true;
        },
      };
    }

    const aHook = useAHook();
    const { loading } = aHook;

    function clickBtn1() {
      aHook.fn();
    }

    return {
      aHook,
      loading,
      clickBtn1,
    };
  },
});
</script>
预期是什么?

在Vue 2.7.14 渲染结果与Vue 3相同。渲染内容为:aHook.loading: true

到底发生了什么?

渲染内容为:aHook.loading: { "value": false }

回答

6

看起来toString 方法应该取消对Ref<T>对象的引用。

这可能是由于 Vue 2 的响应式设计限制造成的。

Vue 3在toDisplayStringJSON.stringify调用中有一个 replacer 参数,但这里没有。