Vue3 组件:父传值

 一个组件要想接受来自父组件的参数,需要显式声明。在使用 <script setup> 的单文件组件中,props 可以使用 defineProps() 宏来声明。

一、defineProps的声明:

第一种:仅声明

最简单的声明方式,不指定类型已经默认值。

defineProps(['name','age'])

第二种:带类型的声明方式。

可声明接受的参数的类型,如果与预期的不符合,会在浏览器控制台上发出警告信息。

defineProps({
    name: String,
    age: String
})

第三种:带类型,带默认值的声明方式。

可以定义一个默认值,当父组件没有传值的时候参数使用该默认值。

defineProps({
    name: {
        type: String,
        default: '李四'
    },
    age: {
        type: Number,
        default: 20
    }
})

第四种:使用lang="ts"的

当父组件,子组件都使用lang="ts"时,开发者工具会提示开发人员类型是否错误,参数是否传递,这有效的避免开发过程中因类型问题导致的一系列问题。

带问号的参数是可选参数。

<script setup lang="ts">
defineProps<{
    name: string,
    age?: number
}>();
</script>

二、defineProps的使用

2.1、父传值用法

普通的传值按照标签元素的写法进行传值:

<template>
    <Zi name="李四" age="20"/>
</template>

<script setup lang="ts">
import Zi from './Zi.vue'
</script>

传递的参数也可以绑定一个动态值,使用v-bind,简写为冒号,如下:

<template>
    <Zi v-bind:name="name" :age="age" />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Zi from './Zi.vue'

const name = ref('李四');
const age = ref(18);
</script>

使用一个对象绑定多个 prop 

这与元素的绑定的用法类似,不写name,age属性,只需要一个v-bind来绑定这个对象即可,对象包含了name,age属性:

ps: 当子组件要求age的类型为Number的时候,普通的传值方法age="16"其实无法满足Number的类型要求。只能使用v-bind:age="16"的写法。

其他类型,如Boolean,Array ,List同理,需要使用动态传值的方法。

2.2、子接受值的用法

 在模版中直接使用,已经自动解包。

<template>
    <div>
        {{ '名字:' + name }}
        <br>
        {{ '年龄' + age }}
    </div>
</template>

<script setup>
defineProps(['name','age'])
</script>

在脚本中使用,需要用一个变量或常量接受defineProps的返回值,然后使用该常量来调用参数。

<template>
    <div>
        {{ '名字:' + name }}
        <br>
        {{ '年龄' + age }}
    </div>
</template>

<script setup>
const props =  defineProps(['name','age'])
console.log(props.name);
console.log(props.age);
</script>

 三、defineProps传值规则

3.1、单向数据流

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

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

const props = defineProps(['foo'])

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

当我们想要修改的props的时候,不如将其作为初始值,定义一个新的响应式变量。

const props = defineProps(['initialCounter'])

// 计数器只是将 props.initialCounter 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
const counter = ref(props.initialCounter)

ps: 对于数组或对象的porps来说,由于是引用类型的对象,我们无法修改其引用,但大概率是能修改其内部值。而对 Vue 来说,禁止这样的改动,虽然可能生效,但有很大的性能损耗,比较得不偿失。

大多数需要修改父组件的状态的时候,应该抛出一个事件来通知父组件做出改变!!

3.2、Prop 校验

Vue 组件可以更细致地声明对传入的 props 的校验要求。比如我们上面已经看到过的类型声明,如果传入的值不满足类型要求,Vue 会在浏览器控制台中抛出警告来提醒使用者。这在开发给其他开发者使用的组件时非常有用。

要声明对 props 的校验,你可以向 defineProps() 宏提供一个带有 props 校验选项的对象,例如:

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'
    }
  }
})

3.3、boolean类型转换

例如,disabled、readonly这些属性,本身的值为true或false。vue对其有着特别的转换规则:

声明:

defineProps({
  disabled: Boolean
})

 使用:

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

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

当一个 prop 被声明为允许多种类型时,Boolean 的转换规则也将被应用。然而,当同时允许 String 和 Boolean 时,有一种边缘情况——只有当 Boolean 出现在 String 之前时,Boolean 转换规则才适用:

// disabled 将被转换为 true
defineProps({
  disabled: [Boolean, Number]
})
  
// disabled 将被转换为 true
defineProps({
  disabled: [Boolean, String]
})
  
// disabled 将被转换为 true
defineProps({
  disabled: [Number, Boolean]
})
  
// disabled 将被解析为空字符串 (disabled="")
defineProps({
  disabled: [String, Boolean]
})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值