在Vue3中,`props`接收的`type`类型有以下几种:

1.String:字符串类型

2.Number:数字类型

3.Boolean:布尔类型

4.Array:数组类型

5.Object:对象类型

6.Date:日期类型

7.Function:函数类型

8.Symbol:符号类型

9.[Custom Types]:自定义类型

你也可以使用数组形式来表示多种类型的组合,

比如`[String, Number]`表示接收字符串或数字类型的值。

另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。

注意:以上是常见的`type`类型列表,你也可以自定义其它类型。

`props`还有两个参数:

default: 默认值

required: 是否必传, true必传,false 非必传

开启必传时 若不传则警告[Vue warn]: Missing required prop: “xxx”

父组件代码(测试默认值):

测试props传参常见的数据类型

import {defineComponent,reactive,onMounted,toRefs} from 'vue'import Child from './Child.vue'// vue3.0语法export default defineComponent({name: '父组件名',components: {Child,},setup() {// 在Vue3中,`props`接收的`type`类型有以下几种:// 1. String:字符串类型// 2. Number:数字类型// 3. Boolean:布尔类型// 4. Array:数组类型// 5. Object:对象类型// 6. Date:日期类型// 7. Function:函数类型// 8. Symbol:符号类型// 9. [Custom Types]:自定义类型// 你也可以使用数组形式来表示多种类型的组合,// 比如`[String, Number]`表示接收字符串或数字类型的值。// 另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。// 注意:以上是常见的`type`类型列表,你也可以自定义其它类型。const state = reactive({date: new Date(1998, 12, 31),message: 'Hello World',count: 666,isActive: true,list: [1, 2, 3],user: {name: '张三',age: 18,},callback: () => {console.log('父组件传入的callback执行了')},})onMounted(() => {//})return {...toRefs(state),}},})

子组件代码:

message: {{ message }}

count: {{ count }}

isActive: {{ isActive }}

list: {{ list }}

{{ item }}

date: {{ date }}

user: {{ user }}

import { defineComponent, onMounted } from 'vue'// vue3.0语法export default defineComponent({name: '子组件名',props: {message: {type: String, // type 类型required: true, // required 是否必传, true必传 若不传则警告[Vue warn]: Missing required prop: "message"},count: {type: Number,default: 0, // default 默认值},isActive: {type: Boolean,default: false,},list: {type: Array,default: () => [],},date: {type: Date,default: () => new Date(),},user: {type: Object,default: () => ({ name: 'John Doe', email: 'johndoe@mail.com' }),},callback: {type: Function,default: () => {},},},setup(props) {onMounted(() => {console.log('props', props)})return {//}},})

页面数据显示效果(只传了必填项message):

可以看到,接收到的props只有message是父组件传来的值,而子组件显示的其它值都是定义在default里的默认值,点击callback按钮(调用父组件函数)也是没有任何反应的。

修改父组件代码(将各种数据类型传入):

测试props传参常见的数据类型

import {defineComponent,reactive,onMounted,toRefs} from 'vue'import Child from './Child.vue'// vue3.0语法export default defineComponent({name: '父组件名',components: {Child,},setup() {// 在Vue3中,`props`接收的`type`类型有以下几种:// 1. String:字符串类型// 2. Number:数字类型// 3. Boolean:布尔类型// 4. Array:数组类型// 5. Object:对象类型// 6. Date:日期类型// 7. Function:函数类型// 8. Symbol:符号类型// 9. [Custom Types]:自定义类型// 你也可以使用数组形式来表示多种类型的组合,// 比如`[String, Number]`表示接收字符串或数字类型的值。// 另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。// 注意:以上是常见的`type`类型列表,你也可以自定义其它类型。const state = reactive({date: new Date(1998, 12, 31),message: 'Hello World',count: 666,isActive: true,list: [1, 2, 3],user: {name: '张三',age: 18,},callback: () => {console.log('父组件传入的callback执行了')},})onMounted(() => {//})return {...toRefs(state),}},})

页面数据显示效果(各种数据类型传入了):

可以看到数据将以父组件传入的值为准,default的值被覆盖。点击callback按钮(调用父组件函数)也执行了。

踩坑小案例:

案例:父组件的数据是从接口异步请求来的 ,而子组件是会先挂载的,如果子组件接受的值是从父组件的接口里取来的,想在子组件onMounted的时候拿到这个数据来发请求却没拿到。

修改代码(看下案例):

父组件代码

测试props传参常见的数据类型

import {defineComponent,reactive,onMounted,toRefs} from 'vue'import Child from './Child.vue'// vue3.0语法export default defineComponent({name: '父组件名',components: {Child,},setup() {// 在Vue3中,`props`接收的`type`类型有以下几种:// 1. String:字符串类型// 2. Number:数字类型// 3. Boolean:布尔类型// 4. Array:数组类型// 5. Object:对象类型// 6. Date:日期类型// 7. Function:函数类型// 8. Symbol:符号类型// 9. [Custom Types]:自定义类型// 你也可以使用数组形式来表示多种类型的组合,// 比如`[String, Number]`表示接收字符串或数字类型的值。// 另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。// 注意:以上是常见的`type`类型列表,你也可以自定义其它类型。const state = reactive({id: '',date: new Date(1998, 12, 31),message: '',count: 666,isActive: true,list: [1, 2, 3],user: {name: '张三',age: 18,},callback: () => {console.log('父组件传入的callback执行了')},})onMounted(() => {// 模拟一个接口请求setTimeout(() => {state.id = '父组件请求接口得来的id'}, 3000)})return {...toRefs(state),}},})

子组件代码:

message: {{ message }}

count: {{ count }}

isActive: {{ isActive }}

list: {{ list }}

{{ item }}

date: {{ date }}

user: {{ user }}

import { defineComponent, onMounted } from 'vue'// vue3.0语法export default defineComponent({name: '子组件名',props: {id: {type: String, // type 类型required: true, // required 是否必传, true必传 若不传则警告[Vue warn]: Missing required prop: "message"},message: {type: String, // type 类型required: true, // required 是否必传, true必传 若不传则警告[Vue warn]: Missing required prop: "message"},count: {type: Number,default: 0, // default 默认值},isActive: {type: Boolean,default: false,},list: {type: Array,default: () => [],},date: {type: Date,default: () => new Date(),},user: {type: Object,default: () => ({ name: 'John Doe', email: 'johndoe@mail.com' }),},callback: {type: Function,default: () => {},},},setup(props) {onMounted(() => {console.log('props', props)console.log('props.id:', props.id)// 想拿到id后请求接口// axios.get('props.id').then(res => {// console.log(res)// })})return {//}},})

案例显示效果(取不到id):

父组件请求接口的数据最终会在子组件更新,但是想在onMounted里使用却是拿不到的,因为接口还没请求完成,没拿到该数据,我们来尝试解决这个问题。

解决方案1(v-if):

修改父组件代码:

测试props传参常见的数据类型

import {defineComponent,reactive,onMounted,toRefs} from 'vue'import Child from './Child.vue'// vue3.0语法export default defineComponent({name: '父组件名',components: {Child,},setup() {// 在Vue3中,`props`接收的`type`类型有以下几种:// 1. String:字符串类型// 2. Number:数字类型// 3. Boolean:布尔类型// 4. Array:数组类型// 5. Object:对象类型// 6. Date:日期类型// 7. Function:函数类型// 8. Symbol:符号类型// 9. [Custom Types]:自定义类型// 你也可以使用数组形式来表示多种类型的组合,// 比如`[String, Number]`表示接收字符串或数字类型的值。// 另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。// 注意:以上是常见的`type`类型列表,你也可以自定义其它类型。const state = reactive({id: '',date: new Date(1998, 12, 31),message: '',count: 666,isActive: true,list: [1, 2, 3],user: {name: '张三',age: 18,},callback: () => {console.log('父组件传入的callback执行了')},})onMounted(() => {// 模拟一个接口请求setTimeout(() => {state.id = '父组件请求接口得来的id'}, 3000)})return {...toRefs(state),}},})

解决方案1(v-if)页面效果

在使用子组件的标签上加上,没有拿到id时子组件并不会渲染,当然接口如果过慢的话子组件也会渲染更慢。

解决方案2(父组件不加v-if,子组件用watchEffect):

父组件代码:

测试props传参常见的数据类型

import {defineComponent,reactive,onMounted,toRefs} from 'vue'import Child from './Child.vue'// vue3.0语法export default defineComponent({name: '父组件名',components: {Child,},setup() {// 在Vue3中,`props`接收的`type`类型有以下几种:// 1. String:字符串类型// 2. Number:数字类型// 3. Boolean:布尔类型// 4. Array:数组类型// 5. Object:对象类型// 6. Date:日期类型// 7. Function:函数类型// 8. Symbol:符号类型// 9. [Custom Types]:自定义类型// 你也可以使用数组形式来表示多种类型的组合,// 比如`[String, Number]`表示接收字符串或数字类型的值。// 另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。// 注意:以上是常见的`type`类型列表,你也可以自定义其它类型。const state = reactive({id: '',date: new Date(1998, 12, 31),message: '',count: 666,isActive: true,list: [1, 2, 3],user: {name: '张三',age: 18,},callback: () => {console.log('父组件传入的callback执行了')},})onMounted(() => {// 模拟一个接口请求setTimeout(() => {state.id = '父组件请求接口得来的id'}, 3000)})return {...toRefs(state),}},})

子组件代码

message: {{ message }}

count: {{ count }}

isActive: {{ isActive }}

list: {{ list }}

{{ item }}

date: {{ date }}

user: {{ user }}

import { defineComponent, onMounted, watchEffect } from 'vue'// vue3.0语法export default defineComponent({name: '子组件名',props: {id: {type: String, // type 类型required: true, // required 是否必传, true必传 若不传则警告[Vue warn]: Missing required prop: "message"},message: {type: String, // type 类型required: true, // required 是否必传, true必传 若不传则警告[Vue warn]: Missing required prop: "message"},count: {type: Number,default: 0, // default 默认值},isActive: {type: Boolean,default: false,},list: {type: Array,default: () => [],},date: {type: Date,default: () => new Date(),},user: {type: Object,default: () => ({ name: 'John Doe', email: 'johndoe@mail.com' }),},callback: {type: Function,default: () => {},},},setup(props) {onMounted(() => {console.log('onMounted props', props)console.log('onMounted props.id:', props.id)// 想拿到id后请求接口// axios.get('props.id').then(res => {// console.log(res)// })})watchEffect(() => {console.log('watchEffect', props.id)if (props.id) {// 想拿到id后请求接口// axios.get('props.id').then(res => {// console.log(res)// })}})return {//}},})

解决方案2watchEffect的页面显示效果:

可以看到子组件的页面依然会先挂载渲染,onMounted虽然拿不到值,但是可以在watchEffect里检测到id有值了再做请求就行了。当然有其它的解决方案也欢迎评论区留言交流。