vue 自定义事件 v-model

本文详细解析了Vue.js中的v-model语法糖,以及如何在自定义组件中实现双向数据绑定。通过实例展示了v-model的工作原理,将其拆分为value属性绑定和input事件监听,并解释了在组件上使用v-model时,如何通过props传递值并触发自定义事件来更新父组件的数据。此外,还介绍了model选项在prop和事件非默认值情况下的使用,帮助读者全面掌握v-model在自定义组件中的应用。
摘要由CSDN通过智能技术生成

看完官网API的介绍,想必是有点懵的,我们可以从v-mode的语法糖来一步一步的理解。

v-mode语法糖:

v-model实现了表单输入的双向绑定。一般我们是这么写的:

// html
<div>
    <input v-model="name" />
</div>

// .vue文件
export default {
    data(){
        return {
            name: '',
        }
    }
}

如何实现双向数据的绑定?其实分为两步:

第一步:将变量name的值绑定到input输入框的值上,即改变name的值可以改变输入框的值。

第二步:监听输入框的Input事件,如果输入框的值发生改变就改变name的值。

所以v-model语法糖的真正的实现是这样的:

// html
<div>
    <input :value="name" @input="inputName($event)" />
</div>

// .vue文件
export default {
    data(){
        return {
            name: '',
        }
    },
    methods: {  
        inputName(){
            this.name = $event.tatget.value;
        }  
    }
}

那现在我们来看一下在自定义组件上使用v-model是如何分解的:

// 父组件 

<div>
    <name-input v-model="name"></name-input> // v-mode语法糖
</div>

<div>
    <name-input :value="name" @input="nameInput"></name-input> // 使用prop传递和事件传递
</div>

export default {
    data(){
        return {
            name: '',
        }
    },
    methods: {  
        nameInput(val){
            this.name = val;
        }  
    }
}



// 子组件

Vue.component('name-input',{
    template:'<input type="text" :value="value" @input="update($event)" />',
    props:['value'],
    methods:{
        update(e){
            this.$emit('input', e.target.value);
        }
    }
})


总结一下:

自定义事件也可以用于创建支持 v-model 的自定义输入组件。记住:

<input v-model="searchText">

等价于:

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

当用在组件上时,v-model 则会这样:

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = val" // val是在父组件中接收$emit传过来的值
></custom-input>

为了让它正常工作,这个组件内的 <input> 必须:

  • 将其 value 特性绑定到一个名叫 value 的 prop 上  。<input :value="value"/>标红的value实际是一个prop,只是名字叫value。
  • 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出。标红的input事件其实是@input,即在子组件$emit事件触发的函数,$emit('input', 传参)  。                            <custom-input  :value="searchText" @input="searchText = val" ></custom-input>

写成代码之后是这样的:

Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

现在 v-model 就应该可以在这个组件上完美地工作起来了:

<custom-input v-model="searchText"></custom-input>

v-model的语法糖理清楚了,那现在来看model的用法,官网API是这样说的:

 可以理解为:model默认为 model:{ prop: 'value', event: 'input'},当使用默认值时 model可以不写,如下:


// 子组件
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <input type="checkbox" @input="change($event)" />
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  methods: {
    change(e){
      console.log(e.target.checked,'111')
      this.$emit('input', e.target.checked)
    }
  }

}
</script>


// 父组件
<template>
  <div id="app">
    <h3 class="title">{{ msg }}</h3>
    <hello-world v-model="msg"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  components:{
    HelloWorld
  },
  data () {
    return {
      msg: 'vue-demo向你问好!',
    }
  }
}
</script>

但是当prop 的默认值不是value,event的默认值不是input时就需要添加model,如下:

// 子组件
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <input type="checkbox" @change="change($event)" :checked= "checked" /> // checked是model.prop的值
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  model: {
    prop: 'checked',
    event: 'checkChange'
  },
  props:['checked'],
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  methods: {
    change(e){
      console.log(e.target.checked,'111')
      this.$emit('checkChange', e.target.checked)  // checkChange 是model.event的值
    }
  }

}
</script>


// 父组件
<template>
  <div id="app">
    <h3 class="title">{{ msg }}</h3>
    <hello-world v-model="msg"></hello-world>
    <button @click="changeCheck">改变</button>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  components:{
    HelloWorld
  },
  data () {
    return {
      msg: true,
    }
  },
  methods:{
    changeCheck(){
      this.msg =!this.msg
    }
  }
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值