Vue 3在子组件中使用v-model

oprakyz7  于 2022-11-25  发布在  Vue.js
关注(0)|答案(5)|浏览(228)

我刚刚发现在Vue 3中,v-model没有对子Component进行响应性/React性工作。
此代码将更新username数据

<template>
  <div>
    <input type="text" v-model="username" placeholder="Insert your username" />
    <p>{{ username }}</p>
  </div>
</template>

<script>
// Home.vue
export default {
  name: 'Home',
  data() {
    return {
      username: 'admin'
    }
  }
}
</script>

如果我在input中键入一些内容,username数据也会改变。
但是,当我像下面的例子一样使用Component时:

<template>
    <input type="text" :class="'input-text ' + additionalClass" :placeholder="placeholder" />
</template>

<script>
// InputText.vue
import { defineComponent } from "vue"

export default defineComponent({
    name: 'InputText',
    props: {
        placeholder: {
            type: String,
            default: ''
        },
        additionalClass: {
            type: String,
            default: ''
        }
    }
})
</script>

然后我更新了代码以使用Component
注:Component注册成功。

<template>
  <div>
    <input-text v-model="username" :placeholder="`Insert your username`" />
    <p>{{ username }}</p>
  </div>
</template>

<script>
// Home.vue
export default {
  name: 'Home',
  data() {
    return {
      username: 'admin'
    }
  }
}
</script>

当我键入一些东西时,username数据没有更新,与前一个不同。
有什么解决方案或至少参考我试图实现什么?

yqyhoc1h

yqyhoc1h1#

你不能指望v-model隐式地为你更新底层元素。换句话说,你仍然需要在组件本身内处理它,并将modelValue公开为一个道具,这样才能真正工作。

<template>
  <input
    type="text"
    @input="onChanged"
    :value="modelValue"
    :class="'input-text ' + additionalClass"
    :placeholder="placeholder" />
</template>

<script>
  // InputText.vue
  import { defineComponent } from "vue"

  export default defineComponent({
    name: 'InputText',

    emits: ['update:modelValue'],

    props: {
      modelValue: String,
      placeholder: {
        type: String,
        default: ''
      },
      additionalClass: {
        type: String,
        default: ''
      }
    },

    setup(props, { emit }) {
      function onChanged(e) {
        emit('update:modelValue', e.currentTarget.value);
      }

      return {
        onChanged
      }
    }
  })
</script>
hmae6n7t

hmae6n7t2#

使用Vue3 script setup语法

<template>
    <input type="text" v-model="val" @input="handleInput">
</template>

<script setup>
    import {ref, defineProps, defineEmit} from 'vue'

    const props = defineProps({
        modelValue: {
            type: String,
            default: ''
        },
    })
    const emit = defineEmits(['update:modelValue'])

    const val = ref(props.modelValue)

    const handleInput = () => emit('update:modelValue', val.value)
</script>
cxfofazt

cxfofazt3#

VueUse帮助器useVModel可以简化处理子组件中的v-model,请参阅https://vueuse.org/core/usevmodel/#usage

<script lang="ts" setup>
import { useVModel } from '@vueuse/core'

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

const model = useVModel(props, 'modelValue', emit)
</script>

<template>
    <input type="text" v-model="model" />
</template>
jobtbby3

jobtbby34#

使用OPTIONS API语法

<template>
    <input type="text" v-model="val" @input="updateText" :value="modelValue">
</template>

<script scoped>
    export default {
        props: {
            modelValue: String,
        },
        methods: {
            updateText(event){
                this.$emit('update:modelValue', event.currentTarget.value)
            }
        }
    }
</script>
hjqgdpho

hjqgdpho5#

在vue2中,这个东西起作用了:

您的InputText组件

<template>
    <input :value="value"
           @input="({target}) => $emit('input', target.value)"/>
</template>

<script>
    export default {
        props: {
            value: {}
        }
    }

父组件

<template>
    <inputText v-model="inputValue"/>
</template>

<script>
    export default {
        components: {inputText},
        data: () => ({
            inputValue: null
        })
    }
</script>

相关问题