情景说明
当父组件使用子组件的时候,
我们可能会需要将某些父组件的变量值 传递 给 子组件,在子组件中进行使用。
此时就有一个 【父组件】传值给【子组件】的动作。
这就是本文我们要讨论的问题。
主要问题有两个 :
1、【子组件】 如何接收值
2、【父组件】如何发送值
传值的方式介绍
vue 中提供了一个
props
的属性,用来作为【子组件】中接收【父组件】传递过来的值。
props
这个属性 的定义,是通过一个叫做defineProps()
的东西来操作的.
defineProps()
这个东西不需要引入,可以直接在<script setup>
使用。
props 的三种声明方式
对于子组件中的props的声明方式有三种:
1、字符串数组的格式;【一般来讲,这种写法比较简单,感觉会比较常用】
2、对象的格式;
3、ts 语法的类型标注 来声明 (也算是对象格式的吧)
字符串数组的格式
<script setup lang="ts">
// 声明 props : 字符串数组的格式
const propsList = defineProps(['titleName','titleContent'])
// 控制台打印一下
console.log('titleName : ',propsList.titleName)
console.log('titleContent : ',propsList.titleContent)
</script>
对象的格式
注意 :
使用对象格式的时候,是需要用key-value 键值对
的方式进行定义;
key
: 就是 定义的 属性值;
value
: 需要是 预期的属性的类型的构造函数,如 【number】 类型的话,就是 【Number】
<script setup lang="ts">
// 声明 props - 对象格式
const propsList = defineProps({
titleName:String, // 注意此处的value 值是 对象类型的构造方法
titleContent:String,
titleNum:Number
})
// 控制台打印一下
console.log('titleName : ',propsList.titleName)
console.log('titleContent : ',propsList.titleContent)
console.log('titleNumber : ',propsList.titleNum)
</script>
类型标注的格式
ts 中类型标注的写法,就像是 泛型的写法一样,也可以使用自定义接口的方式。
写法一 :直接写
<script setup lang="ts">
// 声明 props - ts 类型标注的 - 就像是泛型类型的写法
const propsList = defineProps<{
titleName:string,
titleContent:string,
titleNum:number
}>()
// 控制台打印一下
console.log('titleName : ',propsList.titleName)
console.log('titleContent : ',propsList.titleContent)
console.log('titleNumber : ',propsList.titleNum)
</script>
写法二 :定义接口
<script setup lang="ts">
// 声明 props - ts 类型标注的 - 就像是泛型类型的写法
// 定义一个接口
interface MyProps {
titleName:string,
titleContent:string,
titleNum:number
}
// 通过接口的方式声明 props
const propsList = defineProps<MyProps>()
// 控制台打印一下
console.log('titleName : ',propsList.titleName)
console.log('titleContent : ',propsList.titleContent)
console.log('titleNumber : ',propsList.titleNum)
</script>
props 的传递值写法
【父组件】引入【子组件】之后,通过 【属性的方式】 给子组件传递 在 【props】中定义的内容。
传值有两大类 :静态传值、动态传值(用的较多)。
静态传值 :直接写一个静态的值传递过去;
动态传值 :将父组件的一个变量传递过去,此时父组件的变量发生了变化,子组件接收到的也会随之发生改变。
【注意点】
1、【父组件】给【子组件】传值,这个行为是单向进行的,即,子组件不能通过 props 来向父组件传值;
2、因为这个传值的动作是单项的,因此,不建议在子组件中 直接修改 props 的值,
如果想对props的值进行修改后再使用,推荐通过“计算属性”的方式进行操作。
3、在【父组件】中传值的时候,推荐使用 “中划线”的格式进行属性的赋值,
如 “ title-name = 'abc' ”,这样更加的符合JavaScript的语法规范吧。
定义一个子组件准备接收值
本案例的写法是通过 【自定义接口】的方式声明 props 的
<template>
<!-- 子组件 -->
<div class="childdiv">
子组件 - titleName : {{ propsList.titleName }}
<br>
子组件 - titleNumber : {{ propsList.titleNum }}
<br>
子组件 - titleShow : {{ propsList.titleShow }}
<br>
子组件 - titleList : {{ propsList.titleList }}
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 声明一个变量
const msg = ref('这是子组件的msg变量')
// 声明 props - ts 类型标注的 - 就像是泛型类型的写法
// 定义一个接口
interface MyProps {
titleName:string, // 字符串类型
titleNum:number, // 数字类型
titleShow:boolean, // 布尔类型
titleList:number[] // 数组类型
}
// 通过接口的方式声明 props
const propsList = defineProps<MyProps>()
// 控制台打印一下
console.log('titleName : ',propsList.titleName)
console.log('titleNumber : ',propsList.titleNum)
console.log('titleShow : ',propsList.titleShow)
console.log('titleList : ',propsList.titleList)
</script>
<style scoped>
.childdiv{
width: 300px;
border: 1px solid green;
}
</style>
父组件向子组件传值
写法一 : 静态传值
简单来说,这种写法就是直接给属性赋值。
这种方式除了 字符串 类型的属性,其他的类型在传值的时候都需要添加 【:】才可以,否则会提示错误!
<template>
<div class="basediv">
父组件msg : {{ msg }}
<br>
<br>
<!-- 子组件的使用 -->
<!-- 直接给子组件传递静态的值过去,使用中划线的方式 -->
<ChildComponent title-name="abcd"
:title-num="1024"
:title-show="true"
:title-list="[100,99,88]"/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 引入子组件
import ChildComponent from './ChildComponent.vue'
// 声明父组件的一个变量
const msg = ref('这是父组件的msg变量')
</script>
<style scoped>
.basediv{
width: 400px;
height: 200px;
border: 1px solid red;
}
</style>
运行效果:
写法二 : 动态传值
动态传值,就是 把 【父组件】中的变量传递给【子组件】
这种写法的时候,就需要 所有的属性都要在前面添加【:】
了,表示是动态绑定的。
<template>
<div class="basediv">
父组件msg : {{ msg }}
<br>
<br>
<!-- 子组件的使用 -->
<!-- 动态传值的方式给 【子组件】传值 -->
<ChildComponent :title-name="propsValueObj.titleName"
:title-num="propsValueObj.titleNum"
:title-show="propsValueObj.titleShow"
:title-list="propsValueObj.titleList"/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 引入子组件
import ChildComponent from './ChildComponent.vue'
// 声明父组件的一个变量
const msg = ref('这是父组件的msg变量')
const num = ref(4001)
// 声明一个对象,用来传递给子组件
const propsValueObj = ref({
titleName:'父组件传过去的值',
titleNum:2000,
titleShow:false,
titleList:[1,2,3,4,5]
})
</script>
<style scoped>
.basediv{
width: 400px;
height: 200px;
border: 1px solid red;
}
</style>
运行效果:
写法三 : 直接传一个对象
这种写法实际上是对 【写法二】的一种扩展,
传值时不指定属性名,而是直接使用v-bind
指令 把整个对象传进去,
此时组要注意的是,传递的对象的属性名 需要和 【子组件】中接收的属性名一致,这样才能对应起来。
<template>
<div class="basediv">
父组件msg : {{ msg }}
<br>
<br>
<!-- 子组件的使用 : 直接传递一个对象过去 -->
<ChildComponent v-bind="propsValueObj"/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 引入子组件
import ChildComponent from './ChildComponent.vue'
// 声明父组件的一个变量
const msg = ref('这是父组件的msg变量')
// 声明一个对象,用来传递给子组件
const propsValueObj = ref({
titleName:'父组件直接传了个对象',
titleNum:20,
titleShow:true,
titleList:[100,200,3,4,5]
})
</script>
<style scoped>
.basediv{
width: 400px;
height: 200px;
border: 1px solid red;
}
</style>
运行效果 :