在Vue3中,`props`接收的`type`类型有以下几种:
-
String:字符串类型
-
Number:数字类型
-
Boolean:布尔类型
-
Array:数组类型
-
Object:对象类型
-
Date:日期类型
-
Function:函数类型
-
Symbol:符号类型
-
[Custom Types]:自定义类型
你也可以使用数组形式来表示多种类型的组合,
比如`[String, Number]`表示接收字符串或数字类型的值。
另外,你还可以使用`null`或`undefined`来表示接收任意类型的值。
注意:以上是常见的`type`类型列表,你也可以自定义其它类型。
`props` 还有两个参数:
default: 默认值
required: 是否必传, true必传,false 非必传
开启必传时 若不传则警告[Vue warn]: Missing required prop: "xxx"
父组件代码(测试默认值):
<template>
<div style="font-size: 14px">
<h3>测试props传参常见的数据类型</h3>
<Child :message="message" />
<!--
:count="count"
:isActive="isActive"
:list="list"
:user="user"
:date="date"
:callback="callback
-->
</div>
</template>
<script lang="ts">
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),
}
},
})
</script>
子组件代码:
<template>
<div style="font-size: 14px">
<!-- 子组件内容 -->
<p>message: {{ message }}</p>
<p>count: {{ count }}</p>
<p>isActive: {{ isActive }}</p>
<p>list: {{ list }}</p>
<p v-for="(item,index) in list" :key="index">{{ item }}</p>
<p>date: {{ date }}</p>
<p>user: {{ user }}</p>
<button @click="callback">callback按钮(调用父组件函数)</button>
</div>
</template>
<script lang="ts">
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 {
//
}
},
})
</script>
页面数据显示效果(只传了必填项message):
可以看到,接收到的props只有message是父组件传来的值,而子组件显示的其它值都是定义在default里的默认值,点击callback按钮(调用父组件函数)也是没有任何反应的。
修改父组件代码(将各种数据类型传入):
<template>
<div style="font-size: 14px">
<h3>测试props传参常见的数据类型</h3>
<Child
:message="message"
:count="count"
:is-active="isActive"
:list="list"
:user="user"
:date="date"
:callback="callback"
/>
<!-- 两种命名方式都可以
:is-active="isActive"
:isActive="isActive"
-->
</div>
</template>
<script lang="ts">
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),
}
},
})
</script>
页面数据显示效果(各种数据类型传入了):
可以看到数据将以父组件传入的值为准,default的值被覆盖。点击callback按钮(调用父组件函数)也执行了。
踩坑小案例:
案例:父组件的数据是从接口异步请求来的 ,而子组件是会先挂载的,如果子组件接受的值是从父组件的接口里取来的,想在子组件onMounted的时候拿到这个数据来发请求却没拿到。
修改代码(看下案例):
父组件代码
<template>
<div style="font-size: 14px">
<h3>测试props传参常见的数据类型</h3>
<Child
:id="id"
:message="message"
:count="count"
:is-active="isActive"
:list="list"
:user="user"
:date="date"
:callback="callback"
/>
<!-- 两种命名方式都可以
:is-active="isActive"
:isActive="isActive"
-->
</div>
</template>
<script lang="ts">
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),
}
},
})
</script>
子组件代码:
<template>
<div style="font-size: 14px">
<!-- 子组件内容 -->
<p>message: {{ message }}</p>
<p>count: {{ count }}</p>
<p>isActive: {{ isActive }}</p>
<p>list: {{ list }}</p>
<p v-for="(item,index) in list" :key="index">{{ item }}</p>
<p>date: {{ date }}</p>
<p>user: {{ user }}</p>
<button @click="callback">callback按钮(调用父组件函数)</button>
</div>
</template>
<script lang="ts">
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 {
//
}
},
})
</script>
案例显示效果(取不到id):
父组件请求接口的数据最终会在子组件更新,但是想在onMounted里使用却是拿不到的,因为接口还没请求完成,没拿到该数据,我们来尝试解决这个问题。
解决方案1(v-if):
修改父组件代码:
<template>
<div style="font-size: 14px">
<h3>测试props传参常见的数据类型</h3>
<Child
v-if="id"
:id="id"
:message="message"
:count="count"
:is-active="isActive"
:list="list"
:user="user"
:date="date"
:callback="callback"
/>
<!-- 两种命名方式都可以
:is-active="isActive"
:isActive="isActive"
-->
</div>
</template>
<script lang="ts">
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),
}
},
})
</script>
解决方案1(v-if)页面效果
在使用子组件的标签上加上<Child v-if="id"/>,没有拿到id时子组件并不会渲染,当然接口如果过慢的话子组件也会渲染更慢。
解决方案2(父组件不加v-if,子组件用watchEffect):
父组件代码:
<template>
<div style="font-size: 14px">
<h3>测试props传参常见的数据类型</h3>
<Child
:id="id"
:message="message"
:count="count"
:is-active="isActive"
:list="list"
:user="user"
:date="date"
:callback="callback"
/>
<!-- 两种命名方式都可以
:is-active="isActive"
:isActive="isActive"
-->
</div>
</template>
<script lang="ts">
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),
}
},
})
</script>
子组件代码
<template>
<div style="font-size: 14px">
<!-- 子组件内容 -->
<p>message: {{ message }}</p>
<p>count: {{ count }}</p>
<p>isActive: {{ isActive }}</p>
<p>list: {{ list }}</p>
<p v-for="(item,index) in list" :key="index">{{ item }}</p>
<p>date: {{ date }}</p>
<p>user: {{ user }}</p>
<button @click="callback">callback按钮(调用父组件函数)</button>
</div>
</template>
<script lang="ts">
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 {
//
}
},
})
</script>
解决方案2watchEffect的页面显示效果:
可以看到子组件的页面依然会先挂载渲染,onMounted虽然拿不到值,但是可以在watchEffect里检测到id有值了再做请求就行了。当然有其它的解决方案也欢迎评论区留言交流。