$emit("事件名", 数据) 向父组件发送消息;父组件用 $emit("事件名", 数据) 向父组件发送消息;父组件用 $emit("事件名", 数据) 向父组件发送消息;父组件用
Vue 词条目录
前端Wiki/Vue/深入/组件基础

自定义事件与双向绑定

子组件通过 $emit("事件名", 数据) 向父组件发送消息;父组件用 @事件名="处理函数" 监听。配合 props,就构成了最基础的数据流闭环:父向下传 props,子向上抛事件。

「双向绑定」的经典实现就是这个闭环:子组件 props 接收 modelValue,input 时 emit update:modelValue;父组件 <comp v-model="x"> 是这两步的语法糖。Vue 3 还支持多个 v-model(v-model:title、v-model:open)。

  • 子 emit 事件名推荐用 update:xxx 形式(配合 v-model)
  • v-model="x" 展开为 :model-value="x" @update:model-value="x = $event"
  • 一个组件可绑定多个 v-model:v-model:title 与 v-model:open
HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>自定义事件与双向绑定</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
  <div id="app">
    <!-- v-model 语法糖:等价于
         :model-value="age" @update:model-value="age = $event" -->
    <p>父组件年龄:{{ age }}</p>
    <age-input v-model="age"></age-input>
  </div>

<script>
  const { createApp, ref } = Vue;
  const app = createApp({
    setup() {
      const age = ref(18);
      return { age };
    }
  });

  app.component('age-input', {
    props: ['modelValue'],
    emits: ['update:modelValue'],
    template: `
      <div>
        <input :value="modelValue"
               @input="$emit('update:modelValue', Number($event.target.value))">
        <button @click="$emit('update:modelValue', modelValue + 1)">+1</button>
      </div>`
  });

  app.mount('#app');
</script>
</body>
</html>
本节要点v-model 的本质::model-value 传入 + @update:model-value 抛回;子组件改值必须走 emit。