Vue 自定义组件的 v-model 和 .sync 修饰符

Vue 自定义组件的 v-model

Vue 组件的提供 model 选项自定义组件的 v-model 属性。

model 选项的值是一个对象,包含两个参数:

  • prop - [String] 一个属性名
    • 这个属性需要在 props 中声明
    • v-model 会传入这个属性
  • event - [String] 一个当前组件的自定义事件名
    • model 可以监听这个事件
    • 当事件触发($emit)时,将 v-model 的属性值修改为事件传入的值
    • 相当于父级使用组件时默认绑定了事件处理函数修改v-model传入的属性:@myModuleEvent="(val) => { vModelProp = val}"

表单示例

// comp.vue
<template>
  <div>
    <input
      type="checkbox"
      :checked="mychecked"
      @change="$emit('mychange', $event.target.checked)"
    />
  div>
template>

<script>
export default {
  model: {
    prop: 'mychecked', // 需要在props中声明
    event: 'mychange' // 自定义事件名
  },
  props: {
    mychecked: Boolean
  }
}
script>
// About.vue
<template>
  <div>
    <Comp v-model="checked" />
    checked: {{ checked }}
  div>
template>

<script>
import Comp from '@/components/Comp'
export default {
  components: { Comp },
  data() {
    return {
      checked: false
    }
  }
}
script>

效果:

在这里插入图片描述

它类似这样实现:

// Comp.vue
<template>
  <div>
    <input
      type="checkbox"
      :checked="mychecked"
      @change="$emit('mychange', $event.target.checked)"
    />
  div>
template>

<script>
export default {
  props: {
    mychecked: Boolean
  }
}
script>
// About.vue
<template>
  <div>
    <Comp :mychecked="checked" @mychange="checked = $event" />
    checked: {{ checked }}
  div>
template>

<script>
import Comp from '@/components/Comp'
export default {
  components: { Comp },
  data() {
    return {
      checked: false
    }
  }
}
script>

$event 是事件处理函数接收的参数。
mychange事件处理函数的传参,也就是$emit传入的参数。
它也可以写成:

<Comp :mychecked="checked" @mychange="
	val => {
		checked = val
	}
" />

.sync 修饰符

自定义 v-model 实现了子组件修改父组件数据,也就是父子组件数据双向绑定。

它实现的方式是:

  • 通过 prop 接收父组件的数据,用于展示
    • 而不是直接绑定到某个元素的 v-model上,这样会报错
  • 通过 $emit 提交事件,传入新的值
  • 父组件执行事件处理函数更新数据
    • 自定义 v-model 默认会指定父组件的事件处理函数为 val => {property=val}

Vue 的事件名可以定义为这样 updata:prop 以表达对prop赋新值的意图。

例如:v-on:update:mytitle="title"

组件内部将通过$emit('update:mytitle', value)触发事件,修改title的值为value

虽然 eslint-plugin-vue 不认同 xxx:yyy这样的事件名风格,但update:yyy这种是例外,因为它是为了支持.sync修饰符。

示例:

// About.vue
<template>
  <div>
    
		<Comp :mytitle="title" @update:mytitle="title = $event" />
    title: {{ title }}
  div>
template>
<script>
export default {
  data() {
    return {
      title: 'About'
    }
  }
}
script>

// Comp.vue
<template>
  <div>
    <input
      placeholder="请输入内容"
      :value="mytitle"
      @input="$emit('update:mytitle', $event.target.value)"
    />
  div>
template>

<script>
export default {
  props: ['mytitle']
}
script>

Vue 的.sync修饰符可以简化这种方式。

它直接通过v-bind:prop.sync 的方式,简化了两件事情:

  • 绑定 prop
  • 绑定 update:prop 事件
    • 处理函数为val => {property=val}
// About.vue
<Comp :mytitle.sync="title" />
title: {{ title }}

注意:

  • 组件内部需要$emit触发的事件名,格式为update:prop
  • 使用.sync修饰符 同 v-model 一样,必须绑定一个 property 名,不能是一个表达式 或 字面量

你可能感兴趣的:(vue)