最新版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数据是单向的,其内容包含以下:

  • 基础数据,如字符串、数字
  • 数组
  • 对象
  • 函数
相关推荐
01_ice2 小时前
前端学习JS(3)
前端·javascript·学习
无懈可击2 小时前
Vue 低代码可视化 AI 表单设计器 FcDesigner v3.5 版本发布!
前端·vue.js·前端框架
Web - Anonymous2 小时前
Vue3 + Element Plus 集成 JSON Editor 实现实时校验 JSON 编辑器(高亮/暗亮主题/分栏回显/组件复用) - 附完整示例
vue.js·编辑器·json
Hilaku2 小时前
外包前端和大厂前端,写的代码到底有什么本质区别?
前端·javascript·程序员
YHHLAI2 小时前
React `useState` 深入浅出
前端·javascript·react.js
斯内普吖3 小时前
(开源)农产品电商系统实战指南 基于 Java + SpringBoot + Vue + MySQL
java·vue.js·spring boot·mysql·开源
半个落月3 小时前
用 Harness 工程化缓解 LLM 幻觉:Best of N Sampling + LLM as Judge 实战
javascript·人工智能
三十而立洋3 小时前
从 0 到 1:我用 VS Code API + Git 命令写了一个"代码统计"插件
javascript
daols883 小时前
vue 甘特图 vxe-gantt 紧前紧后依赖关系连接线配置详解
前端·vue.js·甘特图
云浪3 小时前
如何让大模型操作 MySQL 数据库?
javascript·人工智能·后端