Я сделал пользовательский компонент ввода и хочу получить данные из него в родительском компоненте. Сначала я использовал компонент так, как написано в гайде:
Input.vue
<input
:value = "value"
@input = "$emit('input', $event.target.value)"
class = "w-full border-[1px] bg-transparent p-4 lg:text-sm placeholder:text-[#97999B]"
:placeholder = "placeholder"
:class = "statusStyles"
/>
MyComponent.vue
<Input
placeholder = "Phone number"
type = "text"
v-model = "phone"
/>
Все заработало, но я разбил этот код на компоненты и появилась еще одна обертка, она выглядит так:
Form.vue
<OrderFormInfo
v-if = "step === 'info'"
:name = "name"
:apart = "apart"
:city = "city"
:phone = "phone"
:postal = "postal"
:region = "region"
:address = "address"
@next-step = "handleNext"
/>
OrderInfo.vue
<Input
placeholder = "phone number"
type = "text"
v-model = "phone"
/>
<Input
placeholder = "recipient name"
type = "text"
v-model = "name"
/>
Input.vue
<template>
<div class = "w-full space-y-[10px]">
<input
:value = "value"
@input = "$emit('input', $event.target.value)"
class = "w-full border-[1px] bg-transparent p-4 lg:text-sm placeholder:text-[#97999B]"
:placeholder = "placeholder"
:class = "statusStyles"
/>
<p v-if = "errorStatus" class = "text-red-500">{{ errors[0] }}</p>
</div>
</template>
<script>
export default {
props: {
errors: Array,
sucess: Boolean,
value: String,
errorStatus: Boolean,
placeholder: String,
},
computed: {
statusStyles() {
if (this.errorStatus) {
return "border-red-500 text-red-500";
}
if (!this.errorStatus && this.value.length > 3) {
return "bg-white border-black text-black";
}
return "text-black border-[#97999B]";
},
},
};
</script>
Как получить данные из OrderInfo.vue в Form.vue? Я пытался передать данные через реквизит, но vue выдает ошибку, что вы не можете этого сделать. Я не понимаю, как использовать v-модель с вложенными компонентами
Ошибка, которую вы получили, говорит о том, что вы не должны изменять значение свойства напрямую через дочерний компонент. Чтобы решить эту проблему, вы должны использовать emits в OrderInfo.vue
.
@Amini Я не понимаю, как это сделать, мне нужно получить данные в Form.vue через $emit?
Событие Do and Emit в OrderInfo
, получение от него значений и использование в Form.vue
Вы можете наблюдать за реквизитом, используя функцию наблюдателя в вашем родительском (Form.vue
) компоненте внутри хука mounted
.
Вам нужно просто прикрепить ref
к самому верхнему дочернему компоненту. Например:
<order-form-info :name = "name" :phone = "phone" ref = "orderFormComponent"></order-form-info>
Живая демонстрация:
Vue.component('orderFormInfo', {
props: ['name', 'phone'],
template: `<div>
<input-field
placeholder = "phone number"
type = "text"
v-model = "phone"/>
<input-field
placeholder = "recipient name"
type = "text"
v-model = "name"/>
</div>`
});
Vue.component('inputField', {
props: ['value', 'placeholder'],
template: `<input
:value = "value"
@input = "$emit('input', $event.target.value)"
:placeholder = "placeholder"
/>`
});
var app = new Vue({
el: '#form',
data: {
name: 'Alpha',
phone: '1111111111'
},
mounted() {
this.$watch(
"$refs.orderFormComponent.phone", (newVal, oldVal) => {
console.info(newVal, oldVal)
}
);
}
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id = "form">
<order-form-info :name = "name" :phone = "phone" ref = "orderFormComponent"></order-form-info>
</div>
Я смог решить это таким образом, я нашел статью в Интернете. Вот изменения:
OrderFormInfo.vue
<Input
placeholder = "Phone number"
type = "text"
:error-status = "false"
:errors = "[]"
:value = "phone"
@input = "$emit('input-phone', $event)"
/>
OrderForm.vue
<OrderFormInfo.
v-if = "step === 'info'"
:name = "name"
@input-name = "name = $event"
:phone = "phone"
@input-phone = "phone = $event"
@next-step = "handleNext"
/>
Есть несколько способов сделать это. Например-
Приведенные выше два решения требовали некоторой установки. Самый простой способ — использовать this.$root.$emit
для передачи события любому компоненту без использования какой-либо глобальной переменной, шины или реквизита.
Вот рабочая демонстрация. Попробуйте изменить значения телефона и имени в поле ввода (OrderFormInfo.vue
), и вы должны увидеть изменения в Form.vue
(родительский компонент).
Vue.component('orderFormInfo', {
props: ['prop_name', 'prop_phone'],
data() {
return {
name: this.prop_name,
phone: this.prop_phone,
}
},
watch: {
name(newVal, oldVal) {
this.$root.$emit('onNameUpdate', newVal);
},
phone(newVal, oldVal) {
this.$root.$emit('onPhoneUpdate', newVal);
}
},
template: `<div>
<b>OrderFormInfo.vue</b><br>
<input-field
placeholder = "phone number"
type = "text"
v-model = "phone"/>
<input-field
placeholder = "recipient name"
type = "text"
v-model = "name"/>
</div>`
});
Vue.component('inputField', {
props: ['value', 'placeholder'],
template: `<input
:value = "value"
@input = "$emit('input', $event.target.value)"
:placeholder = "placeholder"
/>`
});
var app = new Vue({
el: '#app',
data() {
return {
name: 'My Name',
phone: '9090909090'
}
},
created() {
this.$root.$on('onNameUpdate', (name) => {
this.name = name;
});
this.$root.$on('onPhoneUpdate', (phone) => {
this.phone = phone;
})
}
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id = "app">
<b>Form.vue</b><br>
Name - {{ name }} <br>
Phone - {{ phone }} <br><br>
<order-form-info :prop_name = "name" :prop_phone = "phone"></order-form-info>
</div>
Важно-
Когда вы передаете реквизиты из Form.vue
в OrderFormInfo.vue
, не пытайтесь изменить этот реквизит напрямую. Сначала скопируйте свойства в переменную данных и измените их. Читайте причину здесь.
Обычно вы можете и должны передавать данные через реквизит. Может ли быть так, что в ошибке указано, что вы пытались настроить эти реквизиты? Вы должны скопировать эти реквизиты в объекты данных, если это так :)