Vue3中props传参方式详解

 更新时间:2023年11月29日 14:24:20   作者:俊哥前端工程师  
这篇文章主要为大家详细介绍了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的资料请关注脚本之家其它相关文章!

相关文章

  • 如何在vue项目中使用百度地图API

    如何在vue项目中使用百度地图API

    这篇文章主要介绍了如何在vue项目中使用百度地图API,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
    2021-04-04
  • 如何给element plus中动态form-item增加校验的可行方法

    如何给element plus中动态form-item增加校验的可行方法

    文章主要介绍了ElementPlus中动态生成el-form-item时如何使用内置校验机制,通过设置prop属性和使用行内定义规则,结合v-model绑定响应式数据,实现动态表单项的校验,还提到可以定义规则函数优化代码,并在提交时统一提示校验未通过的错误
    2026-04-04
  • VUE递归树形实现多级列表

    VUE递归树形实现多级列表

    这篇文章主要为大家详细介绍了VUE递归树形实现多级列表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Vue中.prettierrc文件的常见配置(浅显易懂)

    Vue中.prettierrc文件的常见配置(浅显易懂)

    这篇文章主要介绍了Vue中.prettierrc文件的常见配置,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Vue列表页渲染优化详解

    Vue列表页渲染优化详解

    这篇文章主要为大家详细介绍了Vue列表页渲染优化的操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • vue设置页面背景及背景图片简单示例

    vue设置页面背景及背景图片简单示例

    这篇文章主要给大家介绍了关于vue设置页面背景及背景图片的相关资料,在Vue项目开发中我们经常要向页面中添加背景图片,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • vue项目实现文件下载进度条功能

    vue项目实现文件下载进度条功能

    这篇文章主要介绍了vue项目实现文件下载进度条功能,本文通过具体实现代码给大家介绍的非常详细,需要的朋友可以参考下
    2021-09-09
  • Vue创建浅层响应式数据的实例详解

    Vue创建浅层响应式数据的实例详解

    这篇文章主要介绍了Vue创建浅层响应式数据的实例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • 基于vue-cli vue-router搭建底部导航栏移动前端项目

    基于vue-cli vue-router搭建底部导航栏移动前端项目

    这篇文章主要介绍了基于vue-cli vue-router搭建底部导航栏移动前端项目,项目中主要用了Flex布局,以及viewport相关知识,已达到适应各终端屏幕的目的。需要的朋友可以参考下
    2018-02-02
  • vue前端实现打印下载示例详解

    vue前端实现打印下载示例详解

    这篇文章主要为大家介绍了vue前端实现打印下载示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论