#vue.js #vuejs3
Вопрос:
Использование Vue3
Я создаю пользовательский компонент и хотел бы привязать события к входным данным внутри него. Поэтому в этом случае я хотел бы сделать что-то подобное, как я делаю с v-bind="inputProps"
этим . Как это делается, сейчас $listeners
удаляются? Как вы, вероятно, видите, я не в состоянии использовать v-bind="$attrs"
, поскольку свойства разделены на то, куда они «идут».
Я здесь, чтобы решить проблему, но любые намеки на улучшение всегда являются приятным бонусом.
// c-текст.vue
<template>
<input
v-if="useAsSingleElement"
v-bind="inputProps"
:class="['c-text', 'c-text--is-single-element']"
@input="$emit('input', $event)"
@blur="$emit('blur')"
@focus="$emit('focus')">
<c-form-item-shell
v-else
:id="id"
:is-required="isRequired"
:label-text="labelText"
:icon="icon"
:icon-class="iconClass"
:errors="errors"
:information="information">
<template #element>
<input
v-bind="inputProps"
class="c-text"
@input="$emit('input', $event.target.value)"
@blur="$emit('blur')"
@focus="$emit('focus')">
</template>
</c-form-item-shell>
</template>
<script>
import { computed } from 'vue'
import CFormItemShell from '@/components/c-form-item-shell.vue'
export default {
components: {
CFormItemShell
},
props: {
useAsSingleElement: { type: Boolean, required: false, default: false },
name: { type: String, required: true },
type: { type: String, required: false, default: 'text' },
placeholder: { type: String, required: false, default: null },
maxlength: { type: [String, Number], required: false, default: null },
minxlength: { type: [String, Number], required: false, default: null },
pattern: { type: String, required: false, default: null },
readonly: { type: Boolean, required: false, default: false },
spellcheck: { type: Boolean, required: false, default: false },
autocomplete: { type: Boolean, required: false, default: true },
id: { type: String, required: true },
isRequired: { type: Boolean, required: false, default: false },
labelText: { type: String, required: false, default: null },
icon: { type: String, required: false, default: null },
iconClass: { type: String, required: false, default: null },
errors: { type: [String, Array], required: false, default: null },
information: { type: [String, Array], required: false, default: null }
},
emits: ['input', 'blur', 'focus'],
setup (props) {
const inputProps = computed(() => {
return {
id: props.id,
name: props.name ? props.name : props.id,
type: props.type,
placeholder: props.placeholder,
maxlength: props.maxlength,
minlength: props.minlength,
pattern: props.pattern,
readonly: props.readonly,
spellcheck: props.spellcheck,
autocomplete: props.autocomplete ? 'on' : 'off'
}
})
return {
inputProps
}
}
}
</script>
Ответ №1:
На основе руководства по миграции :
В виртуальном DOM Vue 3 прослушиватели событий теперь являются просто атрибутами с префиксом
on
и как таковые являются частью$attrs
объекта, поэтому$listeners
были удалены.
так что просто проходите свои мероприятия, как onClick
onBlur
… и
export default {
inheritAttrs: false
}
Комментарии:
1. Я видел документы, но не знал, как их использовать. Три основные вещи, которые неясны. 1. достаточно ли этого делать
<c-text @click="something" />
и не выделять в компоненте? 2. как я могу собрать все события в одно вычисленное? 3. как мне привязать это вычисленное значение к входным данным?
Ответ №2:
Чтобы ответить на мой собственный вопрос и дать более подробный ответ в надежде, что это может помочь кому-либо в будущем. Спасибо Буссаджре Брахиму, чей ответ заставил меня задуматься. Я сделал следующее
- добавлен
inhertsAttrs: false
Ссылка на документы
Это делает так , чтобы события (то есть ваши @input
и т. @click
Д.) в компоненте не применялись к родительскому узлу
- добавлен
emits: ['update:modelValue', 'blur', 'focus']
Ссылка на документы
Это должны быть все выбросы, которые вы хотите захватить и выпустить обратно
- «Соберите» излучение вручную на мой
propsAndListeners
объект, как это. Затем привяжите его к входу, например<input v-bind="propsAndListeners" />
Имейте в виду, что вам нужно указать префикс для ваших событий, on
поэтому, если у вас есть @click
событие, имя onClick
которого будет указано в $attrs
(@ short is v-on)
const propsAndListeners = computed(() => {
return {
onInput: (event) => emit('update:modelValue', event.target.value)
}
})
В большинстве случаев вы, вероятно, привязали $attrs
бы элемент к элементу, но причина в propsAndListeners
том, что у меня есть if
условие и привязка одних и тех же вещей для ввода в двух местах.
Вот полная часть сценария
export default {
components: {
CFormItemShell
},
props: {
useAsSingleElement: { type: Boolean, required: false, default: false },
name: { type: String, required: true },
type: { type: String, required: false, default: 'text' },
modelValue: { type: [String, Number, Date], required: false, default: null },
placeholder: { type: String, required: false, default: null },
maxlength: { type: [String, Number], required: false, default: null },
minxlength: { type: [String, Number], required: false, default: null },
pattern: { type: String, required: false, default: null },
readonly: { type: Boolean, required: false, default: false },
spellcheck: { type: Boolean, required: false, default: false },
autocomplete: { type: Boolean, required: false, default: true },
id: { type: String, required: true },
isRequired: { type: Boolean, required: false, default: false },
labelText: { type: String, required: false, default: null },
icon: { type: String, required: false, default: null },
iconClass: { type: String, required: false, default: null },
errors: { type: [String, Array], required: false, default: null },
information: { type: [String, Array], required: false, default: null }
},
emits: ['update:modelValue', 'blur', 'focus'],
setup (props, { emit }) {
const propsAndListeners = computed(() => {
return {
id: props.id,
name: props.name ? props.name : props.id,
type: props.type,
placeholder: props.placeholder,
value: props.modelValue,
maxlength: props.maxlength,
minlength: props.minlength,
pattern: props.pattern,
readonly: props.readonly,
spellcheck: props.spellcheck,
autocomplete: props.autocomplete ? 'on' : 'off',
onInput: (event) => emit('update:modelValue', event.target.value),
onBlur: (event) => emit('blur', event),
onFocus: (event) => emit('focus', event)
}
})
return {
propsAndListeners
}
}
}