v-model的原理
<input v-model="searchText">
等价于:
|
在组件身上用v-bind绑定一个值,然后通过绑定的input事件,将 $event.target.value的值赋给v-bind绑定的值实现v-model数据的双向绑定。
同样自定义组件也是这个原理:
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
官网是这样说的:
为了让它正常工作,这个组件内的 <input>
必须:将其 value
attribute 绑定到一个名叫 value
的 prop 上
在其 input
事件被触发时,将新的值通过自定义的 input
事件抛出,一般默认事件是input
使用场景
父传子我们一般使用props,在一些自己封装的组件当中,我们可能会需要修改props,这时就可以利用v-model的原理,通过在子组件触发自定义事件,在父组件内修改props的值。
vue2
在子组件身上写v-model(实际上是v-model:value),在子组件内部可以监测value值,监测值发生变化时,触发自定义emit事件,可以改掉父组件传递过来的props值而不引起警告。
model属性
在定义 vue
组件时,你可以提供一个 model
属性,用来定义该组件以何种方式支持 v-model
。
model
属性本身是有默认值的,如下:
// 默认的 model 属性
export default {
model: {
prop: 'value',
event: 'input'
}
}
也就是说,如果你不定义 model
属性,或者你按照当面方法定义属性,当其他人使用你的自定义组件时,v-model="modelVersionListModalVisible"
就完全等价于 :modelVersionListModalVisible="foo"
加上 @input="foo = $event"
model属性写法
//父组件里面
<ModelVersionListModal
v-model="modelVersionListModalVisible"
:modelId="currentDetail.id"
/>
//子组件
<template>
<Modal
v-model="visible"
:title="$t('版本管理')"
:width="800"
footer-hide
>
</Modal>
</template>
<script>
export default {
name: 'ModelVersionListModal',
model: {//model属性
prop: 'value',
event: 'change'//默认是input,可以修改
},
props: {
value: {
type: Boolean,
default: false
},
modelId: {
type: [String, Number],
required: true
}
},
data () {
return {
visible: false
}
},
watch: {
value: {
handler (val) {
this.visible = val
},
immediate: true
},
visible (val) {
this.$emit('change', val)
}
},
}
</script>
不用model的写法
当然这里也可以不配置model属性,使用this.$emit('input',val)
<script>
export default {
name: 'ModelVersionListModal',
props: {
value: {
type: Boolean,
default: false
},
modelId: {
type: [String, Number],
required: true
}
},
data () {
return {
visible: false
}
},
watch: {
value: {
handler (val) {
this.visible = val
},
immediate: true
},
visible (val) {
this.$emit('input', val)
}
},
}
</script>
如果不用v-model,用的v-bind写法,则需要添加@自定义事件
vue3
父组件将props传递给子组件,子组件在对应的时机定义自定义事件,将数据传递给父组件,在父组件改props的值
//父组件
let visible = ref<boolean>(false)
<UpdateModal
:visible="visible"
@Cancel:visible="(val) => (visible = val)"
></UpdateModal>
//子组件定义自定义事件
emit('Cancel:visible', false)