Vue3 在子组件中使用 v-model

Posted

技术标签:

【中文标题】Vue3 在子组件中使用 v-model【英文标题】:Vue3 use v-model in Child Components 【发布时间】:2021-02-21 01:01:08 【问题描述】:

我刚刚发现在 Vue3 中,v-model 无法响应/响应子级 Component 工作。

此代码将更新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 数据没有更新,与之前的不同。

是否有任何解决方案或至少可以参考我想要实现的目标?

【问题讨论】:

【参考方案1】:

您不能指望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>

【讨论】:

我遇到了这个确切的问题,但我使用的是一个计算属性(带有选项 api),它有一个 get() 和 set().. 感谢这个答案,我能够替换 :value="value" :value="modelValue"this.$emit("input", val)this.$emit("update:modelValue", val)【参考方案2】:

使用 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 = defineEmit(['update:modelValue'])

    const val = ref(props.modelValue)

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

【讨论】:

帮了我很多谢谢!我发现您的代码中有错字,或者他们更改了命名。它应该被称为 defineEmits 并带有一个 's'。【参考方案3】:

在 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>

【讨论】:

以上是关于Vue3 在子组件中使用 v-model的主要内容,如果未能解决你的问题,请参考以下文章

Vue3 父子组件通信

vue props原理

五vue3.0之组件通信详解(definePropsdefineEmitsdefineExpose)

Vue3中使用setup监听props

Vue3中使用setup监听props

前端学习笔记(14)-Vue3组件传参