vue的model选项

vue中的v-model指令实现了表单的双向绑定,官网例子:

<input type="text" v-model="message" />
<p>{{message}}</p>

其实v-model只是语法糖,真正的实现形式:

<input type="text" :value="message" @input="message = $event.target.value" />
  1. 将输入框的值绑定到message变量上,这只是单向的,改变message的值可以改变inputvalue,但是改变input的输入不会改变message
  2. 监听input事件,当输入内容时,改变message变量,从而实现了双向绑定。

从官网上看到,v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • texttextarea元素使用value属性和input事件
  • checkboxradio使用checked属性和change事件
  • select使用valuechange事件

实现自定义输入框组件v-model,即双向绑定

Vue.component('custom-input', {
  // 监听input,输入时触发自定义组件内部的updateVal事件
  template: `<input :value="value" @input="updateVal($event.target.value)" type="text"></input>`,
  // 通过props传递,实现父组件值绑定到输入框的value
  props: ["value"],
  methods: {
    // 触发父组件上的input事件
    updateVal(val) {
      this.$emit("input", val);
    }
  }
});
<template>
  <div id="app">
    // 父组件的value值绑定price
    <price-input :value="price" @input="onInput"></price-input>
  </div>
</template>
<script>
var app = new Vue({
  el: '#app',
  data() {
    price: ''
  },
  methods: {
    // 传递过来的值赋给父组件的price变量,实现了输入框到父元素的单向绑定
    onInput(val) {
      this.price = val;
    }
  }
})
</script>
  • 通过上面的分析,默认情况下,一个组件上的v-model会把value用作prop且把input用作event
  • 所以当我们在一个自定义组件上使用v-model并不能实现双向绑定,因为自定义组件并没有默认的value和input事件,在使用时,我们需要按照上面那样显示的去声明定义这些东西。
  • 这时,model选项就派上用场了,在定义组件的时候,指定prop的值和监听的事件。
<template>
  <input type="text" :value="uname" @input="updateVal($event.target.value)" />
</template>
<script>
Vue.component('my-input', {
  model: {
    prop: 'uname',
    event: 'changeXXX' // 随便命名事件,对应下面的```$emit```即可
  },
  props: {
    uname: {
      type: String,
      default: 'tom'
    }
  },
  methods: {
    updateVal(val) {
      this.$emit('changeXXX', val);
    }
  }
})
</script>

然后,父组件使用v-model就可以了

<template>
  <my-input v-model="name" value="some value"></my-input>
  <p>{{name}}</p>
</template>

等价于

<my-input :uname="name" @changeXXX="val => {foo = val}" value="some value"></my-input>
posted @ 2023-09-14 10:31  m2maomao  阅读(67)  评论(0编辑  收藏  举报