在( 自定义 )组件上使用 v-model
v-model 本质上不过是语法糖:它负责监听用户的输入事件以更新数据,并对以下极端场景作出特殊处理。
简单来说就是:在内部为不同的输入元素使用不同的属性并抛出不同的事件。
v-model 默认情况下,只接受 value 属性和响应 input 事件 — 因为 v-model 本身就是基于 input 定制的,而,value 属性是 input 内部定制的绑定值的属性,input 事件是内部定制的当值发生改变时触发的事件。
// HTML {{msg}} // 下面两个表达式,实现的是同样的效果 <input type="text" v-model="msg"> <input type="text" :value="msg" @input="msg = $event.target.value"> // 所以说,v-model 只不过是一种语法糖的形式: // input 组件上本身就有一个 oninput 事件,每当输入框内容发生变化的时候,就会触发这个事件,然后把input的值通过@emit传递出去。 // JS data(){ return { msg:'测试内容' } }
使用场景:子组件想要使用父组件的值,又想去修改父组件的值
# 实现方式 1( 常规 ):props + $emit / 实现方式 2( 语法糖 ):v-model
// 父组件 <template> <div id="app"> <!-- 常规方式 --> <Child :value="msg" @input="msg = $event"></Child> <!-- v-model 语法糖 --> <Child v-model="msg"></Child> </div> </template> <script> import Child from './components/child' export default { name: "App", data(){ return { msg:'测试内容' } }, components:{ Child } }; </script>// 子组件 <template> <div class="content"> {{value}} <div @click="clickBtn">点击</div> </div> </template> <script> export default { props:{ value:'' }, methods:{ clickBtn(){ this.$emit('input','子组件内容') } } } </script>
# 实现方式 3:定制 v-model - model 选项
Problem:子组件中的 value 属性被占用了,如何实现 v-model ?
- 官网解释:model 选项,允许一个自定义组件在使用 v-model 时定制 prop 和 event。
- 默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event, 但是一些输入类型,比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。
- 使用 model 选项可以回避这些情况产生的冲突。
// 父组件 <template> <div id="app"> <!-- v-model 语法糖 --> <Child v-model="msg"></Child> </div> </template> <script> import Child from './components/child' export default { name: "App", data(){ return { msg:'测试内容' } }, components:{ Child }, }; </script>// 子组件 <template> <div class="content"> {{msg1}} <input type="text" :value="msg1" @input="$emit('change1',$event.target.value)"> </div> </template> <script> export default { props:{ msg1:'' }, model:{ prop:'msg1', event:'change1' } } </script>