首页 > 解决方案 > Vue3 v-model 对象不是响应式的

问题描述

我正在尝试使用嵌套组件创建一个表单,其中我传递给子组件的数据可以是对象的嵌套值。

带有字符串的输入字段按预期工作,我只是对象值有问题。提前感谢您的建议!

这是我的沙箱的链接:https ://codesandbox.io/s/vue3-form-54xi8

我的父组件VueVModel.vue

<template>
<div>
  <custom-text-input
    v-model:firstName="firstName"
    v-model:lastName="lastName"
    v-model:address.street="address.street"
  />
  <p>First Name: {{ firstName }}</p>
  <p>Last Name: {{ lastName }}</p>
  <p>Street: {{ address.street }}</p>
</div>
</template>

<script>
import { ref, reactive } from "vue";

import CustomTextInput from "./CustomTextInput.vue";

export default {
components: {
  CustomTextInput,
},

setup() {
  // data
  const firstName = ref("Max");
  const lastName = ref("Testname");
  const address = reactive({
    street: "Milkyway 3",
  });

  return {
    firstName,
    lastName,
    address,
  };
},
};
</script>

我的子组件CustomTextInput.vue

<template>
  <div>
    <p>
      <label> First Name </label>
      <input
        type="text"
        :value="firstName"
        placeholder="First Name"
        @input="$emit('update:firstName', $event.target.value)"
      />
    </p>
    <p>
      <label> Last Name </label>
      <input
        type="text"
        :value="lastName"
        placeholder="Last Name"
        @input="$emit('update:lastName', $event.target.value)"
      />
    </p>
    <p>
      <label> Street </label>
      <input
        type="text"
        :value="street"
        placeholder="Street"
        @input="$emit('update:street', $event.target.value)"
      />
    </p>
  </div>
</template>

<script>
export default {
  props: {
    firstName: String,
    lastName: String,
    street: String,
  },
};
</script>

标签: vuejs3vue-composition-apiv-model

解决方案


您正在传递address.street无法映射到address.street道具中的对象。而是尝试只通过街道。

    <custom-text-input
      v-model:firstName="firstName"
      v-model:lastName="lastName"
      v-model:street="address.street"
    ></custom-text-input>

const app = Vue.createApp({
  setup() {
    // data
    const firstname = Vue.ref('Max');
    const lastname = Vue.ref('Testname');
    const address = Vue.reactive({
      street: 'Milkyway 3',
      zip: 12345,
      city: 'Mars-Village',
    });

    return {
      firstname,
      lastname,
      address,
    };
  }
})

app.component('custom-text-input', {
  template: document.getElementById("CustomTextInputTemplate").innerHTML,
  props: {
    firstname: {
      type: String,
      required: true,
    },
    lastname: {
      type: String,
      required: true,
    },
    street: {
      type: String,
      required: true,
    },
  }
})

app.mount('#app')
<script src="https://unpkg.com/vue@3.0.7/dist/vue.global.prod.js"></script>

<div id="app">
  <div>
    <h1>Form</h1>

    <custom-text-input
      v-model:firstname="firstname"
      v-model:lastname="lastname"
      v-model:street="address.street"
    ></custom-text-input>
    
    <hr />
    <h3> Debugging </h3>
    <p>First Name: {{ firstname }}</p>
    <p>Last Name: {{ lastname }}</p>
    <p>Street: {{ address.street }}</p>
    <div>
      Address-Object:
      <pre>{{ address }}</pre>
    </div>
  </div>
</div>

<template id="CustomTextInputTemplate">
  <div>
    <p>
      <label> First Name </label>
      <input type="text" :value="firstname" placeholder="First Name" @blur="$emit('update:firstname', $event.target.value)" />
    </p>
    <p>
      <label> Last Name </label>
      <input type="text" :value="lastname" placeholder="Last Name" @blur="$emit('update:lastname', $event.target.value)" />
    </p>
    <p>
      <label> Street </label>
      <input type="text" :value="street" placeholder="Street" @blur="$emit('update:street', $event.target.value)" />
    </p>
  </div>
</template>


推荐阅读