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

vue3 里面父组件向子组件传值的一个问题

  •  
  •   zzlit · 2021-08-18 16:49:05 +08:00 · 2212 次点击
    这是一个创建于 974 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 vue2 里面:

    
    // 父组件
    <template>
      <ComponentA v-bind.sync="obj" />
    </template>
    
    
    <script>
    data() {
      return {
        obj: {a: 1, b: 2}
      }
    }
    </script>
    
    
    // 然后在子组件 ComponentA 里面直接去拿 a 和 b 就好了,就相当于是 v-bind 把 obj 拆开了,添加了.sync 修饰符又能同步修改
    props: ['a', 'b']
    
    

    如果按照 vue3 的写法:

    // 父组件
    <template>
      <ComponentA v-model:obj="obj" v-model:c="c" />
    </template>
    
    <script setup lang="ts">
    import { reactive, ref } from 'vue';
    
    const obj = reactive({
      a: 1,
      b: 2
    });
    const c = ref(0)
    </script>
    
    // 子组件
    
    <script setup lang="ts">
    const props = defineProps<{
      obj: {
        a: number;
        b: number;
      };
      c: number;
    }>();
    
    const emit = defineEmits(['update:obj', 'update:c']);
    
    function syncEdit() {
      emit('update:obj', { a: 2, b: 1 }); // 这个没有作用
      emit('update:c', 2); // 这个起作用了
    }
    
    </script>
    

    现在遇到了两问题,求大佬们解答一下:

    1.如何在 vue3 里面把 obj 拆开,并且实现类似于.sync 的效果

    2.为什么 v-model:xxx="xxx",当 xxx 为 reactive 定义的时候不能同步修改,而 ref 可以

    6 条回复    2021-08-26 13:51:02 +08:00
    joe237
        1
    joe237  
       2021-08-18 19:00:33 +08:00
    没人答么,我来稍微回复一下。

    2. 不答,不想答
    1. 其实与 vue2 也差球不多,文档中也有,可能你没注意到。

    ```
    obj: {
    id: 1,
    title: 'My Journey with Vue'
    }

    <component v-bind="post"></component>

    // 等价于:

    <component v-bind:id="post.id" v-bind:title="post.title"></component>

    ```

    参考文档: [here]( https://v3.vuejs.org/guide/component-props.html#passing-the-properties-of-an-object).
    a516307724
        2
    a516307724  
       2021-08-19 10:05:11 +08:00
    第一个没试过就不说了。
    第二个很好解释 reactive 定义的响应市对象本身的,如果要对象里面的值需要响应的话需要用到 toRefs 方法转化
    zzlit
        3
    zzlit  
    OP
       2021-08-19 10:17:53 +08:00
    @joe237 多谢大佬解答,我知道 v-bind 可以用,但是我是想在 v-bind 上在实现原 vue2 中.sync 的作用。
    其实我发现需要实现 1 主要问题在 2,之前一直以为 ref 是针对 string 或 number 这种基本的数据类型的,不能用于 object,结果一直弄错了,ref 会根据数据类型去判断,如果是 object 就会走 reactive 创建这个响应式对象,那么我如果要实现 v-bind.sync 的话其实有两种办法。
    第一种:父组件里面直接用 ref 定义,我的想的是因为在模板上 obj.value 是被解绑的所以直接写 obj 就行了,然后 v-model 的语法糖其实就是更新 obj 的 value,所以直接用 ref 定义可以

    ```
    // 父组件
    <template>
    <ComponentA v-model:obj="obj" />
    </template>

    <script setup lang="ts">
    import { ref } from 'vue';

    const obj = ref({
    a: 1,
    b: 2
    });
    </script>
    ```

    第二种:这个就其实是自己手动拆开了,就是在子组件里面麻烦一点需要定义很多个 update:xxx

    ```
    // 父组件
    <template>
    <ComponentA v-model:a="obj.a" v-model:b="obj.b" />
    </template>

    <script setup lang="ts">
    import { reactive } from 'vue';

    const obj = reactive ({
    a: 1,
    b: 2
    });
    </script>
    ```
    不知道我上面说的对不对
    ps:目前用的是第一种,就是在如果需要在方法里面用的时候是写成 obj.value.a,看起来怪怪的...
    zzlit
        4
    zzlit  
    OP
       2021-08-19 10:25:00 +08:00
    @a516307724 我好像有点懂了,其实就是相当于我上面第二种方法里面 toRefs 把 obj 转化一下一样的道理,v-model 更新的对象的值,就是需要一个 xx.value?


    ```
    // 父组件
    <template>
    <ComponentA v-model:a="a" v-model:b="b" />
    </template>

    <script setup lang="ts">
    import { reactive } from 'vue';

    const obj = reactive({
    a: 1,
    b: 2
    });
    const { a, b } = toRefs(obj);
    </script>
    ```
    JobinJia34
        5
    JobinJia34  
       2021-08-26 10:14:40 +08:00
    ```
    function syncEdit() {
    emit('update:obj', { a: 2, b: 1 }); // 这个没有作用
    emit('update:c', 2); // 这个起作用了
    }
    ```
    这两都能更新啊
    zzlit
        6
    zzlit  
    OP
       2021-08-26 13:51:02 +08:00
    @jiabinbin0115 你父组件的 obj 是不是 ref 定义的?我使用 ref 的可以,用 reactive 不行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5269 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 06:58 · PVG 14:58 · LAX 23:58 · JFK 02:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.