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有值了再做请求就行了。当然有其它的解决方案也欢迎评论区留言交流。

相关推荐
翻滚吧键盘9 分钟前
vue绑定一个返回对象的计算属性
前端·javascript·vue.js
苦夏木禾14 分钟前
js请求避免缓存的三种方式
开发语言·javascript·缓存
超级土豆粉22 分钟前
Turndown.js: 优雅地将 HTML 转换为 Markdown
开发语言·javascript·html
秃了也弱了。28 分钟前
Chrome谷歌浏览器插件ModHeader,修改请求头,开发神器
前端·chrome
乆夨(jiuze)1 小时前
记录H5内嵌到flutter App的一个问题,引发后面使用fastClick,引发后面input输入框单击无效问题。。。
前端·javascript·vue.js
忧郁的蛋~1 小时前
HTML表格导出为Excel文件的实现方案
前端·html·excel
小彭努力中1 小时前
141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
前端·javascript·vue.js·交互
然我2 小时前
别再只用 base64!HTML5 的 Blob 才是二进制处理的王者,面试常考
前端·面试·html
NanLing2 小时前
【纯前端推理】纯端侧 AI 对象检测:用浏览器就能跑的深度学习模型
前端
呆呆的心2 小时前
前端必学:从盒模型到定位,一篇搞定页面布局核心 🧩
前端·css