简体   繁体   English

将数据从父组件传递到子组件时,为什么我不能将数据绑定到我的 v-model?

[英]Why cant i bind data to my v-model when passing data from parent to child component?

I would like to pass data from my parent to child component and bind data to a input field through v-model to display data from my api call in parent component.我想将数据从父组件传递到子组件,并通过 v-model 将数据绑定到输入字段,以在父组件中显示来自 api 调用的数据。 But it seems to be problem when binding to input field i get this error message: Unexpected mutation of "data" prop.eslintvue/no-mutating-props但是绑定到输入字段时似乎有问题我收到此错误消息: Unexpected mutation of "data" prop.eslintvue/no-mutating-props

Partent Component父组件

<script lang="ts">
import { defineComponent,ref } from 'vue';
import axios from 'axios'
import ChildComponent from '../components/ChildComponent.vue';

export default defineComponent({
    Component: { ChildComponent },
    name: 'IndexPage',
    setup() {
        return {
            fixed: ref(false),
            data: []
        };
    },
    mounted() {
        this.getData();
    },
    methods: {
        getData() {
            axios.get('/api/Hotel/' + 2).then((response) => {
                this.data = response.data;
                this.fixed = true,
                    console.log(this.data);
            });
        }
    },
    components: { ChildComponent }
});

</script>

Child Component子组件

<template>
    <main>
        <q-card class="height: 500px; width: 500px">
      <q-card-section>
        <div class="text-h6">Terms of Agreement</div>
        <div class="q-pa-md">
    <div class="q-gutter-md" style="max-width: 300px">
      
    <div>
                <q-input filled v-model="data.message" label="Filled" />

    </div>

    </div>
  </div>
      </q-card-section>

      <q-separator />

      <q-separator />

      <q-card-actions align="right">
        <q-btn flat label="Decline" color="primary" v-close-popup />
        <q-btn flat label="Accept" color="primary" v-close-popup />
      </q-card-actions>
    </q-card>

    </main>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
    props:['data'],
    name: 'ChildComponent',
    setup() {
        return {
            text: ref(''),
        };
    },

});


</script>

I have tried this to make mounted methods in my child components like this:我试过这样在我的子组件中制作安装方法,如下所示:


    <div>
       <q-input filled v-model="dataIn.message" label="Filled" />

    </div>

export default defineComponent({
    props:['data'],
    name: 'ChildComponent',
    setup() {
        return {
            text: ref(''),
            dataIn:{}
        };
    },

    mounted(){
    this.dataIn = this.data
    },
});

It seems to work but not optimal, i lost my data when i refresh my page.它似乎有效但不是最佳的,刷新页面时我丢失了数据。 Anyone have a soulution?有人有解决方案吗?

Props should be read readonly.道具应该只读。 Your dataIn approach needs a watcher that will update your dataIn whenever your data props change您的dataIn方法需要一个观察者,它会在您的data属性更改时更新您的dataIn

optionsApi:选项API:

export default defineComponent({
props:['data'],
name: 'ChildComponent',
data() {
   text: '',
   data: this.dataIn,
}

watcher: {
   dataIn: (newValue,oldValue){
      this.data = newValue
   }
}

}); });

If I understood you correctly, you need to emit event from child or to use computed property with getter/setter:如果我理解正确的话,你需要从 child 发出事件或者将计算属性与 getter/setter 一起使用:

 const { ref, onMounted, watch } = Vue const app = Vue.createApp({ setup() { const items = ref({}) const getData = () => { items.value = ({id: 1, message: 'aaa'}) /*axios.get('/api/Hotel/' + 2).then((response) => { this.data = response.data; this.fixed = true, console.log(this.data); });*/ } onMounted(async() => await getData()) // react to chenges from child const changed = (val) => { items.value.message = val.message } return { //fixed: ref(false), items, changed }; }, }) app.component('ChildComponent', { template: ` <main> <q-card class="height: 500px; width: 500px"> <q-card-section> <div class="text-h6">Terms of Agreement</div> <div class="q-pa-md"> <div class="q-gutter-md" style="max-width: 300px"> <div> <.-- listen to updating --> <q-input filled v-model="text:message" @update,model-value="change" label="Filled" /> </div> </div> </div> </q-card-section> <q-separator /> <q-separator /> <q-card-actions align="right"> <q-btn flat label="Decline" color="primary" v-close-popup /> <q-btn flat label="Accept" color="primary" v-close-popup /> </q-card-actions> </q-card> </main> `: props,['items'], setup(props. {emit}) { const text = ref(props,items) // emit event with changed value const change = () => { emit('changed'. text.value) } // watch for the props changes watch( () => props,items, (newValue. oldValue) => { text;value = newValue; } ), return { text; change }, }. }) app.use(Quasar) app.mount('#q-app')
 <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" type="text/css"> <link href="https://cdn.jsdelivr.net/npm/quasar@2.5.5/dist/quasar.prod.css" rel="stylesheet" type="text/css"> <div id="q-app"> {{items}} <:-- listen to child event --> <child-component:items="items" @changed="changed"></child-component> </div> <script src="https.//cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod:js"></script> <script src="https.//cdn.jsdelivr.net/npm/quasar@2.5.5/dist/quasar.umd.prod.js"></script>

It seems that you want to make change to your data on your child component, you have to make it two-way binding.似乎您想更改子组件上的数据,您必须使其双向绑定。 You should change your child code like this ( you are using custom q-input in your component and the attributes may differ a little but it is the same concept):您应该像这样更改您的子代码(您在组件中使用自定义 q-input 并且属性可能略有不同,但它是相同的概念):

<q-input
        :value="value"
        v-bind="$attrs"        
        v-on="$listeners"
        @input="(v) => $emit('input', v)"
      />

and instead of using data prop you should change it to value:而不是使用数据道具,你应该将它更改为值:

  props: {
    value: {
      type: [String], // multiple type also defenition accepted
      default: "",
    },
}

then in your parent simply use child component like this:然后在您的父母中只需使用这样的子组件:

<your-child-component v-model="someData" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM