V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liuliancc
V2EX  ›  Vue.js

求助 Vue 大佬,为什么使用 reactive 数据没有双向绑定?

  •  
  •   liuliancc · 2025 年 7 月 21 日 · 3556 次点击
    这是一个创建于 180 天前的主题,其中的信息可能已经有所发展或是发生改变。

    萌新小白请教,不太明白为什么使用 ref 数据可以双向绑定,使用 reactive 数据无法双向绑定?是我用法不对吗?
    到底什么时候应该使用 ref 什么时候应该使用 reactive 呢?

    https://play.vuejs.org/#eNp9U8Fu00AQ/ZXRXmJEsIVAHCInElQ9wAEqijj54tqTdMt6d2Wv3UCUOzeEOMAHIHFC8AP8De13MDubpNu09GLtzrx582b9ZiWeWpsOPYqJyLuqldZBh663s0LLxprWwQpanI/pU1ZODghrmLemgREVjXagA9PYTTzN/MVzUrrQWQaV0R3RuvcKD4yeywVMPWey4izMjXbH8gNO4OETjqzvFfr2miDBF+6X+Zo8CxOQdro4bKwqHdINILcwYbJpIVZRadQg3UbhPozscrQuxOzy4+fLb78ufn79++dLnvlHISqedXjQmBoV0UUUhYCMMHkW9RZj4Tqaxnc464ymh2b5haiIRypsX1knadpCTIAzPlcqZc5fcMy1PY638eoUq3e3xM+6pY8V4qjFDtsBC7HLubJdoAvpw+OXuKTzLklT9IrQdyRfY2dU7zUG2LNe1yQ7wrHa5+wEqRdvusOlQ91th/JCPXLN+EKQM/wT/m/0K7mP0sdcR3+XXnHrqn2ngir1gv6DI5rrrg1uGcN56arTPd8SUDts52WFcBy5bM9aum9OaFRNGuKKo9bYLmDZBm9L1RM6IuKSYGLL4CnUOJcauTTn7ywh08a0h410G9qE6Ea9rclEk6sWozEMN1rdm8BgZB11ROLZNWTSnL+bhgGkTFWqG7uVR8SzZAVpmrL+9EoE72eh+VWTiGUMicbzjSaYzsIgXkty6yRMvqtg1rWP1og2uIZjd211LQc+0FGVJ6hmYVUvvv+4+P0pz0JsA5Da9i7a20j5bvU3C0zoLFBfX+X1P0Ky0Q8=

    直接展示代码:

    App.vue

    <script setup>
    import { ref, reactive } from 'vue'
    import Comp from './Comp.vue'
    
    // const styleConfig = ref({
    //  fontSize: 16
    // })
    const styleConfig = reactive({
      fontSize: 16
    })
    </script>
    
    <template>
      <p :style="{ fontSize: styleConfig.fontSize + 'px'}">我是字体</p>
      <Comp v-model="styleConfig" />
    </template>
    
    

    Comp.vue

    <script setup lang="ts">
    import { reactive, watch } from 'vue'
    
    interface StyleConfig {
      fontSize: number
    }
    
    interface Props {
      modelValue: StyleConfig
    }
    const props = defineProps<Props>()
    
    interface Emits {
      (e: 'update:modelValue', value: StyleConfig): void
    }
    const emit = defineEmits<Emits>()
    
    const localConfig = reactive<StyleConfig>({ ...props.modelValue })
    
    watch(localConfig, (newConfig) => {
      emit('update:modelValue', { ...newConfig })
    }, { deep: true })
    </script>
    
    <template>
      <div>
        <label>字体大小</label>
        <input v-model="localConfig.fontSize" />
      </div>
    </template>
    
    18 条回复    2025-07-24 10:15:38 +08:00
    WJYuan
        1
    WJYuan  
       2025 年 7 月 21 日   ❤️ 1
    用法不对,reactive 不能直接替换整个对象
    https://cn.vuejs.org/guide/essentials/reactivity-fundamentals.html
    coli
        2
    coli  
       2025 年 7 月 21 日   ❤️ 1
    举个简单的例子吧:

    ```javascript
    const a = reactive({ b: 1 });
    // some logics ...
    a = { b: 123 };
    ```

    结果会报错,因为你在尝试把 `const` 定义的值赋值为另外一个值。

    而 `<Comp v-model="styleConfig" />` 的语法糖等效为:

    ```vue
    <Comp :modelValue="styleConfig" @update-modelValue="(newVal) => styleConfig = newVal" />
    ```

    这边 `styleConfig = newVal` ,看出问题了吧?

    ---

    而用 `ref` 没问题是因为,ref 用了一层 `.value` 包裹起来,这样你把原来整个对象覆盖掉,改到的都是 `.value` ,而不是 `styleConfig` 这个对象本身。

    不过看原来的代码,把 `v-model="styleConfig.fontSize"` 传出去就好了,这么绕除非你想要用到 `styleConfig` 的其他属性……

    ---

    PS:Vue3 可以用 `defineModel` 写,用起来很爽。

    ---

    PPS: 这也是个 JS 对象地址的问题:

    ```javascript
    const a = [ { x: 1 }, { y: 2 }, { z: 3 } ];
    const b = a[0];
    a[0].x = 2;
    console.log(b); // => { x: 2 }
    a[0] = { x: 3 };
    console.log(b, a[0] === b); // => { x: 2 } , false
    ```
    xuhuanzy
        4
    xuhuanzy  
       2025 年 7 月 21 日 via Android
    reactive 解构后的对象是原始值而不是代理对象。
    liuliancc
        5
    liuliancc  
    OP
       2025 年 7 月 21 日
    感谢各位大佬解惑
    liwenka1
        6
    liwenka1  
       2025 年 7 月 22 日
    应该使用 ref 什么时候应该使用 reactive 呢?
    只使用 ref 即可,虽然要不断的使用 .value 会比较繁琐,但是可以更好的区分响应式数据和非响应式数据
    wangtian2020
        7
    wangtian2020  
       2025 年 7 月 22 日
    reactive 出错时 ref 一定不会出错,弄不明白就一直用 ref 完事儿,.value 一定触发更新
    gogogo2000
        8
    gogogo2000  
       2025 年 7 月 22 日
    js 的对象无论是 getter/setter 还是 proxy 都是一个对象,你直接把对象给替换了,当然就无法监听变化了
    ref 无论你怎么替换,实际上你置换的都是对象的.value 值。

    基本上你可以理解为 ref=reactive{ value: ??? },所以使用 ref 时,ref 对象本身永久都不会变,自然总是可以监听到变动
    hamwong
        9
    hamwong  
       2025 年 7 月 22 日
    没用过 reactive ,ref 一把梭
    erwin985211
        10
    erwin985211  
       2025 年 7 月 22 日
    这种问题直接丢给 ai 就行了
    johnnyyeen
        11
    johnnyyeen  
       2025 年 7 月 22 日
    官方文档有详细说明
    MIUIOS
        12
    MIUIOS  
       2025 年 7 月 22 日
    @erwin985211 每次看到这种无意义的评论就很烦,人家正儿八经问问题非要来一句这种问题直接丢给 ai 就行了,AI 要是能帮楼主解决了楼主还跑来这问人?人家一句话就给解惑了, 换成 AI ,给你输出一大堆文字你还要在里面找到最重要的信息,到头来还是一头雾水
    erwin985211
        13
    erwin985211  
       2025 年 7 月 23 日
    @totoro52 他这么具体的问题为什么不能问 ai ?? ,我不知道 up 是不是问过 ai ,但是我的把它的帖子原封不动丢给 ai 很明确的就得出结论了。你发问题就一定有人回答吗,回答的人的质量就一定高吗。ai 是能够训练了。凭什么说我的回答没意义,如果 up 想我一样直接问题 ai 它的疑问早就解决了。
    sunny2580839896
        14
    sunny2580839896  
       2025 年 7 月 23 日
    统一用 ref
    zhj0326
        15
    zhj0326  
       2025 年 7 月 23 日
    使用 ref 觉得 .value 麻烦的话,可以了解一下 vue macros
    liuliancc
        16
    liuliancc  
    OP
       2025 年 7 月 23 日
    @erwin985211 #13 我的代码是 ai 写的,帖子贴的是简化版代码,当时直接让 ai 改的乱七八糟,改了好几次都不行就想着来论坛问一下,我下次注意
    NerbraskaGuy
        17
    NerbraskaGuy  
       2025 年 7 月 23 日
    @liuliancc #16 其实也不用问 ai ,vue3 reactive 这个东西的弊端被讨论烂了,掘金上面随便找几个文章看一下就很快明白了。
    linkopeneyes
        18
    linkopeneyes  
       2025 年 7 月 24 日
    全用 ref 就好了,reactive 还要过一下脑子,ref 不用动脑
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   1664 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:24 · PVG 00:24 · LAX 08:24 · JFK 11:24
    ♥ Do have faith in what you're doing.