如何在 Vue 2.7 Composition API 中将 v-model 与自定义组件一起使用?

问题描述 投票:0回答:1

我正在使用 Vue 2.7 和 Composition API 构建自定义输入组件。到目前为止,我的组件已达到以下状态:

<template>
  <div class="ui-field">
    <label :for="id">{{ label }}{{ required ? '*' : '' }}</label>
    <input
      :aria-errormessage="errorDescriptionId()"
      :aria-invalid="!!error ? 'true' : 'false'"
      :autocomplete="autocomplete"
      class="ui-input"
      :data-acting="is_acting"
      :disabled="disabled"
      :id="id"
      :required="required"
      :type="type"
      :value="modelValue"
      @input="emitChange"
    />
    <p :id="errorDescriptionId()" v-if="error">{{ error }}</p>
  </div>
</template>

<script lang="ts" setup>
type UIInput = {
  autocomplete?: 'on' | 'off' | undefined
  disabled?: boolean | undefined
  error?: string | undefined
  id?: string | undefined
  is_acting?: boolean | undefined
  label?: string | undefined
  required?: boolean | undefined
  type?: 'text' | 'number' | undefined
  modelValue?: any
}

const props = defineProps<UIInput>()
const emit = defineEmits(['update:modelValue'])

function emitChange(event: Event): void {
  if (event?.target?.value) {
    emit('update:modelValue', event.target.value)
  }
}

function errorDescriptionId(): string | undefined {
  if (props.error === undefined) {
    return undefined
  }

  return `${!!props.id ? props.id : generateRandomId()}-error`
}

function generateRandomId(): string {
  const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  let random_string = ''

  for (let i = 0; i < 4; i++) {
    const index = Math.floor(Math.random() * letters.length)
    random_string += letters.charAt(index)
  }

  return random_string
}
</script>

如您所见,组件应该能够在父组件上接收

v-model
,如下所示:

<UIInput
  autocomplete="off"
  id="complement"
  label="Complemento"
  type="text"
  v-model="form.address.complement"
/>

form.address.complement
是一个响应式对象,它的值应该传递到我的组件的输入元素,并随着我更改输入上的文本而更改。所有这些都是组件应该的行为方式,但实际上,在检查Vue DevTools时,我的
UIInput
有一个
modelValue: undefined
,即使
form.address.complement
已经以字符串值开头,并且还有一个
$attrs: value: [value of form.address.complement]
。就像双向绑定没有正确连接所有东西一样。

我不知道我做错了什么,所以如果有人可以提供帮助,我很感激。

vue.js data-binding vue-component vue-composition-api
1个回答
0
投票

我找到了解决这个问题的方法。唯一需要改变的是

emit
,它需要发出一个名为“input”的事件

emit('input', 'event.target.value')

而且,在

type UIInput
中,我不需要
modelValue
,正如 @Estus Flask 对我的问题的评论,但实际上,一个
value
,它对我的 v 模型有价值。

© www.soinside.com 2019 - 2024. All rights reserved.