【vue3 自定义组件中使用v-model实现双向绑定】


前言

比如我们有自定义的Form组件、Input组件。

如果Form组件想拿到Input组件中input框输入的内容,我们可以让Form这个父组件给Input子组件传值props:value(不能直接修改子组件的props),子组件定义变量记录prop的值,子组件监听数据变化,再用$emit('input')传给父组件,父组件接收调用方法去修改value。

vue3可以使用组件v-model去解决上述问题,从而实现组件的双向数据绑定。v-model是$emit('input')props:value的语法糖。

使用组件 v-model 的主要好处是无需记特定的 prop 字段名,即可绑定到组件中的值,降低组件的使用成本。

简单封装Input组件

Input.vue

<template>
  <div>
    <input type="text"
           :value="inputRef.val"
            @input="updateValue"
    >
  </div>
</template>
// ......
props:{
  modelValue: String // 默认使用 modelValue 作为prop
},
setup(props, context) {
	const inputRef = reactive({
      val: props.modelValue || '', // 不建议直接修改props中的数据
      error: false,
      message: ''
    })
	const updateValue = (e: KeyboardEvent) => {
      const targetValue = (e.target as HTMLInputElement).value
      inputRef.val = targetValue // 拿到更新后的值
      context.emit('update:modelValue', targetValue) // emit传递的方法名必须是update:modelValue
    }
}

在组件中使用Input组件
Form.vue

<template>
    <form>
     <Input v-model="emailVal"/>
    </form>
</template>
// 
<script lang="ts">
import { defineComponent, reactive, ref } from 'vue'
// ....
export default defineComponent({
  name: 'Form.vue',
  components: {
   Input 
  },
  setup () {
    const emailVal = ref('')
    return {
      emailVal
    }
  }
})
</script>

<Input v-model="emailVal"/> 在代码背后,模板编译器会对 v-model 进行更冗长的等价展开。因此上面的代码其实等价于下面这段:


<Input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/

v-mode参数

使用Input组件<Input v-model="emailVal"/>时,input组件默认使用 modelValue 作为prop。
当然也可以自定义<Input v-model:emailVal="emailVal"/>,input组件中就可以使用emailVal作为prop:

props:{
  emailVal: String // 默认使用 modelValue 作为prop
},

多个v-model绑定

此外,也可以有多个v-model绑定,如:

<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>

子组件编写方式:

<script setup>
defineProps({
  firstName: String,
  lastName: String
})

defineEmits(['update:firstName', 'update:lastName'])
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

更多内容详见官方文档Vue官网-组件 v-model

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值