第3章:组件化开发基础

第7节:Props组件通信

3.7.1 Props声明与类型检查

Props是Vue.js中父组件向子组件传递数据的主要方式。在子组件中,我们可以通过props选项声明接收哪些属性,并可以指定类型、默认值、是否必填等验证规则。

基本Props声明

export default {
  props: {
    // 基础类型检查
    title: String,
    // 多个可能的类型
    likes: [String, Number],
    // 必填且为数字
    age: {
      type: Number,
      required: true
    },
    // 带默认值的对象
    config: {
      type: Object,
      default: () => ({ show: true })
    }
  }
}

Props类型

Vue支持以下Props类型:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
  • 自定义构造函数

自定义类型检查

// 自定义构造函数
function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

export default {
  props: {
    author: {
      type: Person,
      validator: (value) => {
        // 自定义验证函数
        return typeof value.firstName === 'string' && typeof value.lastName === 'string'
      }
    }
  }
}

在组合式API中使用Props

<script setup>
// 基础声明
const props = defineProps(['title', 'likes'])

// 带类型检查的声明
const props = defineProps({
  title: String,
  likes: Number
})

// 使用TypeScript类型
interface Props {
  title: string
  likes?: number
}

const props = defineProps<Props>()
</script>

3.7.2 单向数据流原则

Vue.js遵循单向数据流原则:

  • 父组件可以向子组件传递数据(通过Props)
  • 子组件不能直接修改父组件传递的数据
  • 子组件如果需要修改数据,应该通过事件通知父组件,由父组件进行修改

为什么不能直接修改Props?

  1. 可维护性:数据流清晰,容易追踪数据变化
  2. 可预测性:父组件可以完全控制传递给子组件的数据
  3. 避免冲突:防止多个子组件同时修改同一数据导致的冲突

子组件如何响应Props变化?

如果子组件需要根据Props变化执行某些逻辑,可以使用watchcomputed

export default {
  props: ['count'],
  computed: {
    // 基于Props计算新值
    doubleCount() {
      return this.count * 2
    }
  },
  watch: {
    // 监听Props变化
    count(newVal, oldVal) {
      console.log(`count changed from ${oldVal} to ${newVal}`)
    }
  }
}

在组合式API中:

<script setup>
import { computed, watch } from 'vue'

const props = defineProps(['count'])

const doubleCount = computed(() => props.count * 2)

watch(() => props.count, (newVal, oldVal) => {
  console.log(`count changed from ${oldVal} to ${newVal}`)
})
</script>

3.7.3 Prop的大小写命名

在Vue中,Prop的命名需要注意HTML属性和JavaScript属性的差异:

HTML中的kebab-case

在HTML模板中,建议使用kebab-case(短横线分隔)命名:

<my-component post-title="Hello"></my-component>

JavaScript中的camelCase

在JavaScript中,建议使用camelCase(驼峰式)命名:

export default {
  props: ['postTitle'],
  mounted() {
    console.log(this.postTitle) // Hello
  }
}

Vue会自动将kebab-case转换为camelCase,所以以下两种写法是等价的:

<!-- HTML中使用kebab-case -->
<my-component post-title="Hello"></my-component>

<!-- JavaScript中使用camelCase -->
export default {
  props: ['postTitle']
}

在组件模板中使用

在组件的模板中,可以直接使用camelCase或kebab-case访问Props:

<template>
  <div>
    <h1>{{ postTitle }}</h1> <!-- 推荐 -->
    <h1>{{ post-title }}</h1> <!-- 也可以,但不推荐 -->
  </div>
</template>

Props使用最佳实践

  1. 使用明确的类型检查:为Props添加类型检查,提高代码质量
  2. 设置合理的默认值:为可选Props设置默认值,避免undefined错误
  3. 遵循单向数据流:不要直接修改Props,通过事件通知父组件
  4. 使用computed处理Props:对于需要转换的Props,使用computed属性
  5. 合理命名:使用语义化的名称,遵循大小写规范

总结

Props是Vue组件间通信的基础,通过掌握Props的声明、类型检查、单向数据流原则和命名规范,你可以编写出健壮、可维护的组件。记住,Props是只读的,子组件永远不应该直接修改父组件传递的数据。

在下一节中,我们将学习组件间通信的另一种方式:自定义事件。

« 上一篇 单文件组件(SFC) 下一篇 » 自定义事件与组件通信