使用 Vue3
我正在创建一个自定义组件并希望将事件绑定到其中的输入。所以在这种情况下,我想做一些与 v-bind="inputProps"
类似的事情。现在 $listeners
被删除了怎么办?正如您可能看到的,我无法使用 v-bind="$attrs"
,因为属性被划分为它们“去”的位置。
我是来解决问题的,但任何关于改进的提示总是值得欢迎的。
// c-text.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>
答案 0 :(得分:1)
在 Vue 3 的虚拟 DOM 中,事件侦听器现在只是属性,以 on
为前缀,因此是 $attrs
对象的一部分,因此 $listeners
已被删除。>
所以只需传递您的事件,例如 onClick
、onBlur
... 和
export default {
inheritAttrs: false
}
答案 1 :(得分:0)
回答我自己的问题和更详细的答案,希望它可以在未来帮助任何人。感谢 Boussadjra Brahim,他的回答让我开始思考。我做了以下
inhertsAttrs: false
这使得组件上的事件(意味着您的 @input
、@click
等)不会应用于父节点
emits: ['update:modelValue', 'blur', 'focus']
这应该是您想要捕获并发回的所有发射
propsAndListeners
对象。然后将其绑定到输入,如 <input v-bind="propsAndListeners" />
请记住,您必须使用 on
作为您的事件的前缀,因此如果您有一个 @click
事件,该事件将在 onClick
中具有名称 $attrs
(@short是 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
}
}
}