【问题标题】:Why is vue v-model not working for an array prop?为什么 vue v-model 不适用于数组道具?
【发布时间】:2022-01-03 04:30:36
【问题描述】:

我有一个自定义组件,它采用 modelValue 属性并发出 update:modelValue 事件。在父组件中,我传递了一个数组:

TestComponent.vue

<template>
  <div>
     <button @click="updateIt">Test</button>
  </div>
</template>

<script>
export default {
    props: {
       modelValue: Array
    },
    emits: ["update:modelValue"],
    setup(props, {emit}){
        return {
            updateIt(){
                emit("update:modelValue", [4,5,6])
            }
        }
    }
}
</script>

App.vue

<template>
  <div>
     <test-component v-model="myArr"/>
     <ul>
         <li v-for="i in myArr" v-text="i"></li>
     </ul>
  </div>
</template>

<script>
import TestComponent from "./TestComponent.vue";

export default {
    components: {
        TestComponent
    },
    setup(props, {emit}){
        const myArr = reactive([1,2,3]);

        return {
            myArr
        }
    }
}
</script>

当我按下按钮时列表不会更新,为什么?

【问题讨论】:

    标签: javascript vue.js vuejs3 vue-composition-api vue-reactivity


    【解决方案1】:

    在内部,v-model 指令更改为 update:modelValue 事件的处理函数,如下所示:

    $event =&gt; ((exp =&gt; $event) 其中 exp 是指令中的表达式

    这基本上意味着,当发出update:modelValue 事件时,您发出的值直接分配给myArr 变量,有效地替换整个reactive 变量而不触发反应链,因为它不会通过代理。

    如果myArrref([]),vue 检测到它并且处理函数看起来像这样:

    $event =&gt; (exp ? (exp).value = $event : null) 其中 exp 是指令中的表达式

    这意味着通过 ref 代理分配值,触发反应链。

    但是没有内部逻辑来检查传递的表达式是否是一个数组,如果是,会做一些拼接推魔法来保留原始变量,你必须自己做。

    可能的解决方案:

    1) 使用对象键:

     <test-component v-model="myArr.data"/>
    
     ...
    
     const myArr = reactive({
        data: [1,2,3]
     });
    

    2) 使用参考:

     <test-component v-model="myArr"/>
    
     ...
    
     const myArr = ref([1,2,3]);
    

    3) 使用自定义处理函数:

     <test-component :modelValue="myArr" @update:modelValue="onChange"/>
    
     ...
    
     const myArr = reactive([1,2,3]);
    
     function onChange(newval){
       myArr.splice(0, myArr.length, ...newval);
     }
    

    【讨论】:

    • 可能最好的解决方案就是使用ref 而不是reactive。否则这是正确答案...
    • @MichalLevý 你是对的,我编辑了答案
    猜你喜欢
    • 2021-11-03
    • 2020-12-01
    • 2020-12-07
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 2021-09-20
    相关资源
    最近更新 更多