萌新在尝试使用render()
函数编写基于vue3
的自定义组建时遇到需要使用自定v-model
, 查阅了很多资料都没有找到有如何在render()
函数中自定义的相关文章。
在查阅官网和相关书籍以及凭感觉之后琢磨出正确姿势,来给各位大佬做个报告。
v-model的原理
首先我们要知道v-model
是那些事件和属性的语法糖。
<input v-model="value" />
等同于
<input :value="value" @input="value = $event.target.value" />
但是在自定义组建上使用
v-model
时,情况有所不同
<my-input v-model="value"></my-input>
v-model会执行下面的操作:
<my-input
:model-value="value"
@update:model-value="value = $event">
</my-input>
自定义组件使用 v-model
方法一: 使用 input 事件触发 update:modelValue
所以自定义组件中的内部<input>
元素就必须将value属性绑定到modelValue prop上, 在input事件发生时, 使用新的输入值触发update:modelValue事件, 实现代码如下:
<!-- 自定义输入框 -->
<template>
<!-- 使用 input 事件触发 update:modelValue -->
<input :value="modelValue"
@input="$emit('update:modelValue',$event.target.value)"/>
</template>
<script>
export default {
name: 'MyInput',
props: ['modelValue']
}
</script>
方法二: 使用计算属性
在自定义组件中创建v-model
功能的另一种方法是使用计算属性, 在计算属性中定义get()
和set()
方法,get()
方法返回modelValue
属性或用于绑定的任何属, set()
方法为该属性触发相应的$emit
, 修改上述MyInput组件的代码如下所示:
<!-- 自定义输入框 -->
<template>
<input v-model="value" />
</template>
<script>
import { computed } from 'vue'
export default {
name: 'MyInput',
props: ['modelValue'],
setup(){
<!-- 使用计算属性 -->
const value = computed({
get: () => this.modelValue,
set: newValue => this.$emit('update:modelValue', newValue)
})
return {
value
}
}
}
</script>
🌟🌟🌟 在 render()
函数中创建 v-model
功能 🌟🌟🌟
那么问题来了, 在某些情况下, 我们需要使用 render()
函数创建自定义组件, 如何在render()
函数中创建 v-model
功能呢?
这里有一点要注意 vue2
与 vue3
不同的地方, 查看官网文档我们可以得知:
vue2.x
: 一个组件上的v-model
默认会利用名为value
的 prop 和名为input
的事件
vue3.x
: 默认情况下,组件上的v-model
使用modelValue
作为 prop 和update:modelValue
作为事件。
所以在 Vue3
中使用 render()
函我们给原生组件的prop应该为 modelValue
, 触发事件应该为update:modelValue
, 具体代码如下:
<script>
import {h} from 'vue'
export default {
name: 'MyInput',
props: ['modelValue'],
render(){
return h('input',{
modelValue: this.modelValue,
onInput: ($event) => {this.$emit('update:modelValue', $event.target.value)}
})
}
}
</script>
大功告成
有了自定义v-model
我们可以对一些原生的表单组件进行封装, 配合插槽做出各种漂亮的组件, 例如我自己封装的这套组件, 可以使用插槽为输入框添加各种按钮或icon图标.
Vue3
还针对 checked
复选框增加了propstrue-value
和false-value
, 依据这个特性我们可以做出好看的开关按钮.
如果这篇文章对您有帮助, 或者想看封装组件的细节可以在评论区讨论.