Vue3中props传参方式详解
作者:俊哥前端工程师
在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"
父组件代码(测试默认值)
<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有值了再做请求就行了。当然有其它的解决方案也欢迎评论区留言交流。
以上就是Vue3中props传参方式详解的详细内容,更多关于Vue3 props的资料请关注脚本之家其它相关文章!