Передача входных событий от дочернего компонента к родительскому в Nuxt JS Composition API

#typescript #nuxt.js #vuejs3 #vue-composition-api

Вопрос:

Я новичок в Vue 3 и Nuxt JS Composition API (машинопись). Я создаю простой компонент формы/ввода, который, как я ожидал, будет вести себя при использовании на странице, передавая данные от родителя и от ввода дочернего компонента, каждое изменение входного значения будет передаваться родителю и будет обновляться в родительском шаблоне. Но, похоже, родитель не «уловил» излучаемое событие. Ниже приведена структура проекта.

 |components
|----/forms
|-------- vi-form.vue
|-------- vi-input.vue
|pages
|----test.vue
|...everything else is as same as normal Nuxt JS Composition API project
 

компонентыформыvi-файл ввода.vue

 <template lang="pug">
    div()
        input( v-model.trim="_model" :required="_isRequired" )
</template>

<script lang="ts">
import { computed, defineComponent, inject, ref, useContext, watch } from '@nuxtjs/composition-api'

export default defineComponent({
    props: {
        isRequired: {
            type: Boolean
        },
        label: {
            type: String
        },
        model: String
    },
    setup(props, { emit }) {
        const _isRequired = computed(() => {
            return props['isRequired'] || false
        })

        const _label = computed(() => {
            return props['label'] || ''
        })

        const _model = computed({
            get():string {
                if (props['model'] != undefined)
                    return props['model']
                return ''
            },
            set(value: string) {
                emit('update:model', value)
            }
        })

        return { _isRequired, _label, _model }
    },
})
</script>
 

компонентыформыvi-форма.vue

 <template lang="pug">
    form(@submit.prevent='_submitCb')
        slot
        div
            button(type='button' @click='_resetValue = !_resetValue')
                span()
                | {{ _cancelLbl }}
            button(type='submit')
                span()
                | {{ _submitLbl }}
</template>

<script lang="ts">
import { computed, defineComponent, provide, ref } from '@nuxtjs/composition-api'

export default defineComponent({
    props: {
        submitCb: {
            type: Function
        },
        submitLbl: {
            type: String
        },
        cancelCb: {
            type: Function
        },
        cancelLbl: {
            type: String
        },
        resetForm: {
            type: Boolean
        }
    },
    setup(props) {
        const _submitCb = computed(() => {
            if (!props['submitCb']) {
                return () => {
                    console.log('default submit callback')
                }
            }

            return props['submitCb']
        })

        const _submitLbl = computed(() => {
            return props['submitLbl'] || 'Submit'
        })

        const _cancelCb = computed(() => {
            if (!props['cancelCb']) {
                return () => {
                    console.log('default cancel callback')
                }
            }

            return props['cancelCb']
        })

        const _cancelLbl = computed(() => {
            return props['cancelLbl'] || 'Cancel'
        })

        const _resetForm = computed(() => {
            if (props['resetForm'] amp;amp; (props['resetForm'] == true || props['resetForm'] == 'true'))
            {
                return true
            }

            return false
        })

        const _resetValue = ref(false)

        provide('resetValue', _resetValue)

        return { _submitCb, _submitLbl, _cancelCb, _cancelLbl, _resetForm, _resetValue }
    },
})
</script>
 

pagestest.vue

 <template lang="pug">
    div(class="w-50 m-auto")
        vi-form(:submitCb='submit' submitLbl='Submit' class="border")
            vi-input(label="Fullname" :model="fakeData.full_name")

        div(class="p-2 border")
            h2() Form data
            p() Fullname: {{ fakeData.full_name }}
</template>

<script lang="ts">
import { defineComponent, reactive, ref } from '@nuxtjs/composition-api'

export default defineComponent({
    setup() {
        const fakeData = reactive({
            full_name: 'John Doe',
        })
        const submit = () => {
            console.log(fakeData.full_name)
        }

        return { submit, fakeData }
    },
})
</script>
 

My problem it I can not emit the event update:value to parent, I tried emit with input but still it seem that the parent page doesn’t handle this event. I also tested that if I put an input box in parent template and assign `v-model=’fakeData’ on it, I can alter the input’s value in parent and the child’s input value will also changed, but not the other way around.

Another try is that if I explicitly write like this

 vi-input(label="Fullname" :model="fakeData.full_name" @update.value='v => fakeData = v')
 

then it works, I can change the parent’s data from the child component but this method of explicitly adding @update.value in the component is not wrote in anywhere of the Vue documents that I read.

I’ve read articles about passing input data between child and parent component and they all showed this is kind of the correct way to do it but I still don’t understand why my code not working.
Vue 3 document ,
Vue 3 Data down Event up

Could anyone help me on this problem?