官网https://cn.vuejs.org/guide/components/props.html#propsdeclaration
组件基础:https://blog.csdn.net/weixin_43960767/article/details/128399778?spm=1001.2014.3001.5502

Props 声明

如果你正在搭配 TypeScript 使用 <script setup>,也可以使用类型标注声明 props

<script setup lang="ts">
defineProps<{
  title?: string
  likes?: number
}>()
</script>

传递不同的值类型

Number

<!-- 虽然 `42` 是个常量我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :likes="42" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :likes="post.likes" />

Boolean

<!-- 仅写上 prop 但不传值,会隐式转换为 `true` -->
<BlogPost is-published />

<!-- 虽然 `false` 是静态的值,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :is-published="false" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :is-published="post.isPublished" />

单向数据流

所有的 props 都遵循着单向绑定原则props 因父组件更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用数据流将很容易变得混乱而难以理解

另外,每次父组件更新后,所有的子组件中的 props 都会被更新最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告

const props = defineProps(['foo'])

// ❌ 警告!prop 是只读的!
props.foo = 'bar'

导致你想要更改一个 prop需求通常来源于以下两种场景

  1. prop用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是定义一个局部数据属性,从 props获取初始值即可

    const props = defineProps(['initialCounter'])
    
    // 计数器只是将 props.initialCounter 作为初始值
    // 像下面这样做就使 prop 和后续更新无关了
    const counter = ref(props.initialCounter)
    
  2. 需要对传入的 prop 值做进一步转换。在这种情况中,最好是基于prop定义一个计算属性

    const props = defineProps(['size'])
    
    // 该 prop 变更时计算属性也会自动更新
    const normalizedSize = computed(() => props.size.trim().toLowerCase())
    

更改对象 / 数组类型的 props

对象数组作为 props 被传入时,虽然子组件无法更改 props 绑定,但仍然可以更改对象或数组内部的值。这是因为 JavaScript 的对象和数组是按引用传递,而对 Vue 来说,禁止这样的改动虽然可能,但有很大的性能损耗,比较得不偿失

这种更改的主要缺陷是它允许了子组件以某种不明显的方式影响父组件的状态可能会使数据流在将来变得更难以理解。在最佳实践中,你应该可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合。在大多数场景下,子组件应该抛出一个事件通知父组件做出改变

Prop 校验

defineProps({
  // 基础类型检查
  // (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
  propA: Number,
  // 多种可能的类型
  propB: [String, Number],
  // 必传,且为 String 类型
  propC: {
    type: String,
    required: true
  },
  // Number 类型的默认值
  propD: {
    type: Number,
    default: 100
  },
  // 对象类型的默认值
  propE: {
    type: Object,
    // 对象或数组的默认值
    // 必须从一个工厂函数返回
    // 该函数接收组件所接收到的原始 prop 作为参数
    default(rawProps) {
      return { message: 'hello' }
    }
  },
  // 自定义类型校验函数
  propF: {
    validator(value) {
      // The value must match one of these strings
      return ['success', 'warning', 'danger'].includes(value)
    }
  },
  // 函数类型的默认值
  propG: {
    type: Function,
    // 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数
    default() {
      return 'Default function'
    }
  }
})

注意:defineProps() 宏中的参数不可访问 <script setup>定义的其他变量,因为在编译整个表达式都会被移到外部的函数中

运行时类型检查

校验选项中的 type可以是下列这些原生构造函数StringNumberBooleanArrayObjectDateFunctionSymbol

另外,type可以自定义的类或构造函数,Vue 将会通过 instanceof检查类型是否匹配

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
}

// 作为props
defineProps({
  author: Person
})

Boolean 类型转换

defineProps({
  disabled: Boolean
})


<!-- 等同于传入 :disabled="true" -->
<MyComponent disabled />

<!-- 等同于传入 :disabled="false" -->
<MyComponent />

当一个 prop 声明为允许多种类型时,例如

defineProps({
  disabled: [Boolean, Number]
})

无论声明类型的顺序如何Boolean 类型的特殊转换规则都会被应用

原文地址:https://blog.csdn.net/weixin_43960767/article/details/128493478

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_38078.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注