Vue3+vite+Ts+pinia—第七章 props

7.1 defineProps接收参数

props最主要的作用就是接收父组件的传参,在Vue2里直接使用props接收参数即可,而在vue3需要依赖defineProps来接参。

这里举一个简单的例子,父组件传一个数组给子组件渲染出来。下面分别对比一下2和3的语法:

父组件Person.vue:

xml 复制代码
<template>
  <div class="person">
    <Child :list="personList"></Child>
  </div>
</template>

<script lang="ts" setup name="Person">
  import Child from './Child.vue'

  let personList = [
    {id:'asyud7asfd01',name:'张三',age:60},
    {id:'asyud7asfd02',name:'李四',age:18},
    {id:'asyud7asfd03',name:'王五',age:5}
  ]
</script>

子组件Child.vue:

css 复制代码
<template>
  <div class="child">
    <ul>
      <li v-for="p in list" :key="p.id">
        {{ p.name }} -- {{ p.age }}
      </li>
    </ul>
  </div>
</template>

1、Vue2

Vue2的接参方式是把参数放在props里。

xml 复制代码
<script>
export default {
  props: {
    list: null
  }
}
</script>

这里先不限定接参的类型,在后面会详细讲解。

2、Vue3

Vue3的接参方式有点不同,它需要依赖defineProps函数。它里面传入一个数组,里面的每一项是接参的参数名。

xml 复制代码
<script lang="ts" setup>
  defineProps(['list'])
</script>

7.2 使用props参数

对Vue2来说,props的参数跟定义在data里的属性一样,直接使用this.即可读取;但是Vue3相对麻烦一些,它需要先把props存起来,然后再使用。

1、Vue2

xml 复制代码
<script>
export default {
  props: {
    list: null
  },
  mounted() {
    console.log(this.list);
  }
}
</script>

2、Vue3

Vue3可得注意一下,不能直接使用props里的参数,必须先定义一个变量把props存起来,然后再使用。我们先打印一下整个props的结构:

xml 复制代码
<script lang="ts" setup>
  const propParam = defineProps(['list'])
  console.log(propParam)
</script>

实际上它帮我们包裹成一个对象,我们如果要使用,就以键值对来读取即可,例如上面读取list参数,那就是propParam.list。

7.3 限制props参数类型

1、Vue2

Vue2添加类型限制有两种方式,一种是直接在冒号:后面加类型,一种是通过对象里的type进行设置。

xml 复制代码
<script>
export default {
  props: {
    /* 第一种 */
    // list: Array,
    
    /* 第二种 */
    list: {
      type: Array
    }
  }
}
</script>

2、Vue3

Vue3的类型限制是通过defineProps的泛型实现。它里面传入一个对象,通过键值对的方式对每一个参数进行设置。

ini 复制代码
<script lang="ts" setup>
  const propParam = defineProps<{list: Array<object>}>();
</script>

当然如果想使用ts的接口或者自定义类型来进行设置也是可以的,用法一样。

src/types/index.ts:

typescript 复制代码
// 定义一个接口,用于限制person对象的具体属性
export interface PersonInter {
  id:string,
  name:string,
  age:number
}

/* 一个自定义类型 */
export type Persons = PersonInter[]

src/components/child.vue:

xml 复制代码
<script lang="ts" setup>
  import {type Persons} from '@/types'
  const propParam = defineProps<{list: Persons}>();
</script>

注意:使用了泛型来限制参数类型之后,defineProps方法里就不要传数组了,因为它通过泛型就已经知道你要接收的参数了。例如没有添加限制的写法是defineProps(['list']),添加类型限制后就写成defineProps<{list: Persons}>()。

7.4 限制是否必传

1、Vue2

vue2限制参数必传是通过设置required为true,它默认值是非必传的。

xml 复制代码
<script>
export default {
  props: {
    list: {
      type: Array,
      required: true
    }
  }
}
</script>

2、Vue3

vue3分两种情况:第一种是没有限制类型,把数组传入到defineProps里,比如defineProps('list'),那么它默认是非必传的;第二种是使用泛型限制参数类型,比如defineProps<{list: Persons}>(),则它默认是必传的。如果想设置它为非必传,则在限制类型的冒号:前加一个?,写成?:,这也是ts的一种语法。

(1)第一种情况:不限制类型

xml 复制代码
<script lang="ts" setup>
  defineProps(['list'])
</script>

(2)第二种情况:使用泛型限制类型

xml 复制代码
<script lang="ts" setup>
  import {type Persons} from '@/types'
  const propParam = defineProps<{list: Persons}>()
</script>

我们通过?:即可设置成非必传属性。

xml 复制代码
<script lang="ts" setup>
  import {type Persons} from '@/types'
  const propParam = defineProps<{list?: Persons}>()
</script>

7.5 设置默认值

1、Vue2

Vue2的默认值是通过default进行设置的,它同样有两种情况,一种是基本类型,一种是引用类型。基本类型直接写入默认值,而引用类型需要通过函数返回的形式设置默认值。

xml 复制代码
<script>
export default {
  props: {
    // 基本类型
    num: {
      type: Number,
      default: 123
    },
    // 对象类型
    obj: {
      type: Object,
      default: () => {
        return {id: 123, name: 'test'}
      }
    },
    // 数组类型
    list: {
      type: Array,
      default: () => [{id: 123, name: 'test'}]
    },
    // 函数类型
    fn: {
      type: Function,
      default: () => {
        console.log(123)
      }
    }
  }
}
</script>

2、Vue3

Vue3的默认值需要依赖withDefaults函数,withDefaults函数需要传入两个参数,第一个参数把整个defineProps的内容传进去,第二个参数用来设置默认值,它是一个对象,通过键值对的方式对每个属性进行设置。

注意:Vue3跟Vue2对基本类型和引用类型的设置是一样的,基本类型可以直接设置,引用类型需要包裹一个函数返回,像上述代码没有包裹函数则提示警告,只需要添加函数返回即可。

xml 复制代码
<script lang="ts" setup name="Person">
  import {type Persons} from '@/types'
  
  const propParam = withDefaults(defineProps<{list?:Persons}>(), {
    list: () => [{id:'ausydgyu01',name:'康师傅·王麻子·特仑苏',age:19}]
  })
</script>

父组件Person.vue:

xml 复制代码
<template>
  <div class="person">
    <Child></Child>
  </div>
</template>

7.6 示例代码

源码地址:gitee.com/huang_jing_...

文件目录:src_07_props

相关推荐
假如让我当三天老蒯11 小时前
Options API(选项式 API) 和 Composition API(组合式 API)
前端·vue.js·面试
秃头网友小李3 天前
前端难点:keep-alive 缓存什么?RouterView 的 key 为什么要带 scopeId?
前端·vue.js
徐小夕4 天前
JitWord 3.0 正式发布,高精度Word异构解析+复杂组件兼容,打造web端协同Word编辑器
前端·vue.js·算法
奋斗吧程序媛4 天前
补充一个小知识点:有关@click.native
前端·vue.js
英勇无比的消炎药4 天前
一行命令背后:TinyRobot CLI 如何重构 AI 对话接入的效率范式
vue.js·aigc
jay神4 天前
基于 FastAPI + Vue 的宠物领养管理系统
前端·vue.js·python·毕业设计·fastapi·宠物
一杯奶茶¥4 天前
水果销售网站 CRM客户信息管理系统 超市管理系 酒店管理系统 健身房管理系统 在线音乐网站 校园招聘系统
java·vue.js·spring boot·mysql·spring·java项目
英勇无比的消炎药4 天前
一站式搞定品牌风格:TinyRobot 主题定制从入门到精通
vue.js
尽欢i4 天前
Vue3 customRef 封神教程:防抖、本地存储、自动埋点一套搞定,模板干干净净
前端·javascript·vue.js
因_崔斯汀4 天前
Vue 模板编译:HTML 是怎么变成 JS 的?
前端·vue.js