最新版vue3+TypeScript开发入门到实战教程之Vue3详解props

1、概述

上节讲解vue3中ts泛型的应用,这节内容依然会设计到泛型编程内容。props是Properties这个单词的缩写,可翻译为属性。它是父组件向子组件传递数据的桥梁,是子组件的属性。数据可包含以下内容:

  • 基础数据,如字符串、数字
  • 数组
  • 对象
  • 函数

2、如何区别标签属性常见的书写方式

如下设置标签属性,浏览器是如何执行的?

ruby 复制代码
    <h1 a="1+1" :b="1+1" c="x" :d="fish">测试</h1>
  • 没有冒号,按照普通字符串处理
  • 含有冒号,按照j表达式处理,执行js代码

2.1查看浏览器如何显示结果

xml 复制代码
<template>
  <div class="app">
    <h1 a="1+1" :b="1+1" c="x" :d="fish">测试</h1>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let fish = ref('鲫鱼');
</script>

查看调试信息,h1标签处理如下图:

3、通过props传递基本属性数据

  • App为父组件,创建数据fish、price
  • 引用子组件Fish,设置Fish props属性
  • Fish接收props属性,模版中直接使用
xml 复制代码
父组件App
<template>
  <div class="app">
    <h2>父组件:{{ fish }}</h2>
    <button @click="ChangeFish()">改变鱼与价格</button>
    <Fish :name="fish" :price="price"/>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Fish from './components/Fish.vue';
let fish = ref('鲫鱼');
let price = ref(10);
function ChangeFish() {
  fish.value += '~';
  price.value += 1;
}
</script>

子组件Fish

xml 复制代码
<template>
  <h2>我是子组件</h2>
  <h3>{{ name }}</h3>
  <h3>{{ price }}</h3>
</template>
<script setup lang="ts">
let propsData=defineProps(['name', 'price']);
console.log(propsData);
</script>

运行如下图: 注意,在模版中,可直接使用name、price渲染数据,也可使用propsData数据渲染

xml 复制代码
<template>
  <h2>我是子组件</h2>
  <h3>{{ propsData.name }}</h3>
  <h3>{{ propsData.price }}</h3>
</template>

3.1子组件不能改变父组件传统props数据

子组件接收props,是只读的,它无法被更改。所有props数据是单向的。尝试在Fish组件中更改props数据,会发生什么? 首先,代码提示飘红。执行代码,查看效果如下: 当点击按钮时,提示name、price" failed: target is readonly。name与price是只读。

4、props传递数组、对象数据

传递数组与对象数据,与基本类型数据相同。 父组件App代码

xml 复制代码
<template>
  <div class="app">
    <h2>父组件:{{ fish.name }}</h2>
    <h2>父组件:{{ fish.price }}</h2>
    <button @click="ChangeFishAndCat()">改变鱼与价格</button>
    <Fish :fish="fish" :list="cat"/>
  </div>
</template>
<script setup >
import { reactive } from 'vue'
import Fish from './components/Fish.vue';
let fish = reactive({
  name: '鲫鱼',
  price: 100
});
let cat = reactive([
  {
    id:'01',
    name: '波斯猫',
    price:10
  },
  {
    id:'02',
    name: '狸花猫',
    price:20
  },
  {
    id:'03',
    name: '布偶猫',
    price:30
  },
])
function ChangeFishAndCat() {
  fish.name += '~';
  fish.price += 1;
  cat[0].price += 1;
}
</script>

子组件代码

xml 复制代码
<template>
  <div>
    <h2>我是子组件</h2>
    <h3>{{ fish.name }}</h3>
    <h3>{{ fish.price }}</h3>
    <ul>
      <li v-for="item in list" :key="item.id">猫:{{ item.name }}--价格:{{ item.price }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
defineProps(['fish','list']);
</script>

查看运行效果如下图: 代码可看出,父组件App给子组件传递两个数据fish与cat,。子组件默认接受defineProps(['fish','list'])。注意list与cat对应关系。 这样的传递方式,子组件若接收不到数据或者数据类型不正确,如何处理?

4.1props接收限制类型

props含有四种限制类型

  • 不限制,父组件传递任意数据
  • 限制指定类型数据且必须传递数据
  • 限制指定类型数据且可传可不传递数据
  • 当接收数据为空,设置默认类型数据

4.1.1不限制父组件任意传递类型输入

如上文内容父组件传递:,子组件接收defineProps(['fish','list'])。

4.1.2限制指定类型数据且必须传递数据

子组件限制接收类型,需要用到ts泛型。以接收数组数据为例,说明泛型如何使用。

  • 创建数组泛型FishList,Fish组件引入泛型
  • defineProps接受数据时,设置泛型 查看泛型数据的定义:
typescript 复制代码
export interface FishInter{
  id: string,
  name: string,
  price: number,
  num:number
}
export type FishList=Array<FishInter>

定义泛型鱼的基本结构FishInter。定义鱼数组FishList,数组内容结构是FishInter。 在Fish组件中引用FishList

xml 复制代码
<template>
  <div>
    <h2>我是子组件</h2>
    <ul>
      <li v-for="item in list" :key="item.id">猫:{{ item.name }}--价格:{{ item.price }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import {type FishList} from '@/types'
defineProps<{ list: FishList }>();
</script>

若此时父组件App传递list数据或者数据类型不对,就会出错。具体代码查看图片

4.1.3限制指定类型数据且可传可不传递数据

子组件接收数据时,defineProps设置list是否为空,代码如下:

xml 复制代码
<template>
  <div>
    <h2>我是子组件</h2>
    <ul>
      <li v-for="item in list" :key="item.id">猫:{{ item.name }}--价格:{{ item.price }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import {type FishList} from '@/types'
defineProps<{ list?: FishList }>();
</script>

关键代码:defineProps<{ list?: FishList }>(); ###4.1.4当接收数据为空,设置默认类型数据 当父组件数据为空,defineProps接收到的数据为空。用withDefaults函数,设置默认值。

xml 复制代码
<template>
  <div>
    <h2>我是子组件</h2>
    <ul>
      <li v-for="item in list" :key="item.id">猫:{{ item.name }}--价格:{{ item.price }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import {type FishList} from '@/types'
// defineProps<{ list?: FishList }>();
withDefaults(defineProps<{ list?: FishList }>(), {
  list:()=> [
     {
    id:'01',
    name: '默认值',
    price: 10
  }
  ]

})
</script>

注意list接收到是一个箭头函数的返回值,否则报错。

props传递函数

父组件传递函数给子组件,由于props传递数据是单向的,但有时存在子组件需要更改props数据。可通过传递函数让父组件更改。传递函数,它也是子组件给父组件发送消息的方式之一。 子组件Fish

xml 复制代码
<template>
  <div>
    <h2>我是子组件</h2>
    <button @click="changeFish('~')">改变鱼</button>
  </div>
</template>
<script setup lang="ts">
defineProps(['changeFish']);
</script>

父组件App

xml 复制代码
<template>
  <div class="app">
    <h2>{{ fish }}</h2>
    <Fish :changeFish="changeFish" />
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Fish from './components/Fish.vue';
let fish = ref('鲫鱼');
function changeFish(val:any) {
  fish.value+=val
}
</scrip

运行效果如下:

5、总结

props数据是单向的,其内容包含以下:

  • 基础数据,如字符串、数字
  • 数组
  • 对象
  • 函数
相关推荐
~欲买桂花同载酒~3 小时前
项目优化-vite打包优化
前端·javascript·vue.js
kyriewen3 小时前
JavaScript 继承的七种姿势:从“原型链”到“class”的进化史
前端·javascript·ecmascript 6
wangfpp3 小时前
性能优化,请先停手:为什么我劝你别上来就搞优化?
前端·javascript·面试
踩着两条虫3 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(二十):CLI与工具链之构建配置与Vite集成
前端·vue.js·ai编程
踩着两条虫4 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(二十):CLI与工具链之自定义构建插件
前端·vue.js·ai编程
三旬84 小时前
Day.js 源码深度剖析:极简时间库的设计艺术
javascript
清风徐来QCQ4 小时前
js中的模板字符串
开发语言·前端·javascript
SuperEugene5 小时前
Vue3 + Element Plus 表格实战:批量操作、行内编辑、跨页选中逻辑统一|表单与表格规范篇
开发语言·前端·javascript
极梦网络无忧5 小时前
基于 Vite + Vue3 的组件自动注册功能
前端·javascript·vue.js