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

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

  •  
  •   liuliancc · 44 天前 · 2407 次点击
    这是一个创建于 44 天前的主题,其中的信息可能已经有所发展或是发生改变。

    萌新小白请教,不太明白为什么使用 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  
       44 天前   ❤️ 1
    用法不对,reactive 不能直接替换整个对象
    https://cn.vuejs.org/guide/essentials/reactivity-fundamentals.html
    coli
        2
    coli  
       44 天前   ❤️ 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  
       44 天前 via Android
    reactive 解构后的对象是原始值而不是代理对象。
    liuliancc
        5
    liuliancc  
    OP
       44 天前
    感谢各位大佬解惑
    liwenka1
        6
    liwenka1  
       43 天前
    应该使用 ref 什么时候应该使用 reactive 呢?
    只使用 ref 即可,虽然要不断的使用 .value 会比较繁琐,但是可以更好的区分响应式数据和非响应式数据
    wangtian2020
        7
    wangtian2020  
       43 天前
    reactive 出错时 ref 一定不会出错,弄不明白就一直用 ref 完事儿,.value 一定触发更新
    gogogo2000
        8
    gogogo2000  
       43 天前
    js 的对象无论是 getter/setter 还是 proxy 都是一个对象,你直接把对象给替换了,当然就无法监听变化了
    ref 无论你怎么替换,实际上你置换的都是对象的.value 值。

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