Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • Props 与自定义事件

Props 与自定义事件

在 Vue 3 中,组件之间的通信是构建复杂应用的关键。Props 和自定义事件是实现父子组件通信的基础工具:Props 用于从父组件向子组件传递数据,自定义事件则允许子组件向父组件发送消息。本节将详细讲解这两者的用法和注意事项,并通过示例展示如何在实际项目中应用它们。

Props:父组件向子组件传递数据

Props 是组件的属性,允许父组件通过 HTML 属性向子组件传递数据。子组件通过 props 选项声明接收的数据。

1. 基本用法

示例:传递问候语

创建 src/components/Child.vue:

<template>
  <div>
    <p>{{ greeting }}, {{ name }}!</p>
  </div>
</template>

<script>
export default {
  props: {
    greeting: {
      type: String,
      default: 'Hello'
    },
    name: {
      type: String,
      required: true
    }
  },
  setup(props) {
    return { greeting: props.greeting, name: props.name };
  }
};
</script>

在 src/App.vue 中使用:

<template>
  <div>
    <h1>父组件</h1>
    <Child greeting="Hi" name="Alice" />
    <Child name="Bob" /> <!-- 使用默认 greeting -->
  </div>
</template>

<script>
import Child from './components/Child.vue';

export default {
  components: { Child }
};
</script>
  • 效果:
    父组件
    Hi, Alice!
    Hello, Bob!
    
  • 解析:
    • props 定义了 greeting(可选,默认值“Hello”)和 name(必填)。
    • 在 setup 中通过 props 参数访问传入值。

2. Props 的验证

Vue 3 支持对 Props 进行类型检查和约束:

  • type:指定数据类型(如 String、Number、Boolean、Array 等)。
  • default:设置默认值。
  • required:标记是否必填。
  • validator:自定义验证函数。

示例:带验证的 Props

<template>
  <p>年龄:{{ age }}</p>
</template>

<script>
export default {
  props: {
    age: {
      type: Number,
      required: true,
      validator(value) {
        return value >= 0 && value <= 150; // 年龄范围验证
      }
    }
  },
  setup(props) {
    return { age: props.age };
  }
};
</script>
  • 效果:若传入的 age 不符合验证规则,控制台会警告。

3. 动态 Props

使用 v-bind 动态绑定 Props:

<template>
  <div>
    <input v-model="inputName" placeholder="输入姓名" />
    <Child :name="inputName" />
  </div>
</template>

<script>
import { ref } from 'vue';
import Child from './components/Child.vue';

export default {
  components: { Child },
  setup() {
    const inputName = ref('Alice');
    return { inputName };
  }
};
</script>
  • 效果:输入框内容变化时,子组件的 name 实时更新。

注意

  • Props 是只读的,子组件不应直接修改 Props。若需修改,应通过自定义事件通知父组件。

自定义事件:子组件向父组件通信

自定义事件通过 $emit 方法触发,允许子组件主动向父组件发送数据或信号。

1. 基本用法

示例:计数器组件

创建 src/components/Counter.vue:

<template>
  <div>
    <p>计数:{{ count }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup(_, { emit }) { // 使用 context 中的 emit
    const count = ref(0);
    const increment = () => {
      count.value++;
      emit('count-changed', count.value); // 触发自定义事件
    };
    return { count, increment };
  }
};
</script>

在 src/App.vue 中监听:

<template>
  <div>
    <h1>父组件计数:{{ parentCount }}</h1>
    <Counter @count-changed="updateCount" />
  </div>
</template>

<script>
import { ref } from 'vue';
import Counter from './components/Counter.vue';

export default {
  components: { Counter },
  setup() {
    const parentCount = ref(0);
    const updateCount = (newCount) => {
      parentCount.value = newCount;
    };
    return { parentCount, updateCount };
  }
};
</script>
  • 效果:子组件点击按钮时,父组件的 parentCount 同步更新。
  • 解析:
    • 子组件用 emit('count-changed', payload) 触发事件。
    • 父组件用 @count-changed 监听并接收数据。

2. 事件验证

Vue 3 支持声明自定义事件,增强代码可读性和安全性:

<script>
export default {
  emits: ['count-changed'], // 声明事件
  setup(_, { emit }) {
    const count = ref(0);
    const increment = () => {
      count.value++;
      emit('count-changed', count.value);
    };
    return { count, increment };
  }
};
</script>
  • 好处:若触发未声明的事件,Vue 会警告。

带验证的事件

<script>
export default {
  emits: {
    'count-changed': (value) => {
      return typeof value === 'number' && value >= 0; // 验证 payload
    }
  },
  setup(_, { emit }) {
    const count = ref(0);
    const increment = () => {
      count.value++;
      emit('count-changed', count.value);
    };
    return { count, increment };
  }
};
</script>

3. v-model 与自定义事件

Vue 3 支持在组件上使用 v-model,底层依赖自定义事件。

示例:自定义输入组件

创建 src/components/MyInput.vue:

<template>
  <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>

<script>
export default {
  props: {
    modelValue: String // v-model 绑定的值
  },
  emits: ['update:modelValue'] // v-model 约定的事件
};
</script>

在 src/App.vue 中使用:

<template>
  <div>
    <MyInput v-model="text" />
    <p>输入内容:{{ text }}</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import MyInput from './components/MyInput.vue';

export default {
  components: { MyInput },
  setup() {
    const text = ref('');
    return { text };
  }
};
</script>
  • 效果:输入内容时,text 双向同步。
  • 解析:v-model 自动绑定 modelValue Prop 和 update:modelValue 事件。

综合示例

结合 Props 和自定义事件,创建一个任务项组件:

<!-- TaskItem.vue -->
<template>
  <div>
    <span :class="{ completed: done }">{{ task }}</span>
    <button @click="toggleDone">{{ done ? '取消' : '完成' }}</button>
  </div>
</template>

<script>
export default {
  props: {
    task: String,
    done: Boolean
  },
  emits: ['update:done'],
  setup(props, { emit }) {
    const toggleDone = () => {
      emit('update:done', !props.done);
    };
    return { toggleDone };
  }
};
</script>

<style scoped>
.completed {
  text-decoration: line-through;
  color: gray;
}
</style>
<!-- App.vue -->
<template>
  <div>
    <h1>任务列表</h1>
    <TaskItem v-model:done="task1Done" task="学习 Vue 3" />
    <TaskItem v-model:done="task2Done" task="完成项目" />
  </div>
</template>

<script>
import { ref } from 'vue';
import TaskItem from './components/TaskItem.vue';

export default {
  components: { TaskItem },
  setup() {
    const task1Done = ref(false);
    const task2Done = ref(false);
    return { task1Done, task2Done };
  }
};
</script>
  • 效果:点击按钮切换任务完成状态,样式动态更新。

总结

Props 和自定义事件是 Vue 3 组件通信的基础。Props 实现单向数据流,自定义事件支持子组件主动反馈,二者结合可构建灵活的交互逻辑。掌握这些后,你可以轻松处理父子组件间的协作。下一章将深入响应式系统,进一步提升你的 Vue 3 技能!

Last Updated:: 2/23/25, 8:39 PM