v-model在组件中的使用

312 阅读1分钟

我们知道vue的v-model在input中的使用:

<input type="text" v-model="filename" />
<input type="text" :value="filename" @input="filename=$event.target.value"/>

其实上下两种写法效果是一样的,也就是说上面的写法是下面写法的语法糖

那么我们可以这样理解:

在给 input 元素添加 v-model 属性时,默认会把 value 作为元素的属性,把 input 事件作为实时传递 value 的触发事件

既然是这样,我们不妨将v-model用于父子组件中,用于实现父子组件对某个数据的双向绑定

parent.vue

// 父组件
<template>
  <div class="parent">
    <child v-model="inputValue"></child>
    {{inputValue}}
  </div>
</template>

<script>
import child from './child.vue'
export default {
  components: {
    child
  },
  data () {
    return {
      inputValue: ''
    }
  }
}
</script>

child.vue

// 子组件
<template>
  <input type="text" :value="value" @input="$emit('input', $event.target.value)" />
</template>

<script>
export default {
  props: {
    value: {
      type: String
    }
  }
}
</script>

当然,子组件我们也可以这样写:

// 子组件
<template>
  <input type="text" v-model="filename" />
</template>

<script>
export default {
  props: {
    value: {
      type: String
    }
  },
  computed: {
    filename: {
      get() {
        return this.value
      },
      set(val) {
        this.$emit('input', val)
      }
    }
  }
}
</script>

效果如下:

类似的,我们可以得到如下总结:

给组件添加 v-model 属性时,默认会把value 作为组件的属性,把 input作为给组件绑定事件时的事件名

有时间我们不想用 value 当做默认的属性名,也不想把 input 当做事件名。能不能自定义呢?尤大大提供了model属性:

<template>
  <input type="text" v-model="filename" />
</template>

<script>
export default {
  props: {
    value2: {
      type: String
    }
  },
  model: {
    prop: 'value2',
    event: 'abc'
  },
  computed: {
    filename: {
      get() {
        return this.value2
      },
      set(val) {
        this.$emit('abc', val)
      }
    }
  }
}
</script>