Vue3最佳实践 第五章 Vue 组件应用 1( Props )

news2024/11/24 7:17:55

  本章带领大家理解组件、props、emits、slots、providers/injects,Vue 插件 等Vue组件使用的基础知识。

  • 5.1 组件注册
  • 5.2 Props
    • 5.2.1 组件之间如何传值
    • 5.2.2 参数绑定 v-bind
    • 5.2.3 参数类型
    • 5.2.4 props 默认与必填
    • 5.2.5 验证设置
    • 5.2.6 useAttrs 属性设置

第一章 Vue3项目创建 1 Vue CLI 创建vue项目
第一章 Vue3项目创建 2 使用 Webpack 5 搭建 vue项目
第一章 Vue3项目创建 3 Vite 创建 vue项目
第二章 Vue3 基础语法指令
第三章 Vue Router路由器的使用
第四章 VUE常用 UI 库 1 ( element-plus,Ant ,naiveui,ArcoDesign)
第四章 VUE常用 UI 库 2 ( ailwind 后台框架)
第五章 Vue 组件应用 1( Props )
第五章 Vue 组件应用 2 ( Emit )
第五章 Vue 组件应用 3( Slots )
第五章 Vue 组件应用 4 ( provide 和 inject )
第五章 Vue 组件应用 5 (Vue 插件)
第六章 Pinia,Vuex与axios,VueUse 1(Pinia)
第六章 Pinia,Vuex与axios,VueUse 2(Vuex)
第六章 Pinia,Vuex与axios,VueUse 3(VueUse)
第六章 Pinia,Vuex与axios,VueUse 4(axios)

5.1 组件注册

  Vue 3中有一个非常重要的概念是组件注册,一个 Vue 文件可以被引用到别外一个Vue 文件中,在引用的Vue文件模板中可以使用到被引用到Vue 文件。Vue 文件会被“注册”别外的Vue文件中成为它的子组件,这些子组件会被 父 Vue文件中的模板渲染时找到其对应的实现。组件注册有两种方式:全局注册和局部注册。

1 全局注册

使用 vue 根实例进行注册的组件为全局注册。使用的方法app.component() ,简单的理解就是注册给createApp()的组件都是全局组件,它可以在 Vue 应用中全局可用。

import { createApp } from 'vue'
import App from './App.vue'
import index from './components/index.vue';//导入组件index.vue
const app = createApp(App)
app.component('index',index);//注册全局组件
app.mount('#app')

components目录中创建一个index.vue文件。

<script setup></script>
<template>
  <div>欢迎来到zht代码世界</div>
</template>

App.vue中模板中可以使用这个全局组件功能。

<script setup>
</script>
<template>
<index/>------------使用了全局组件index
</template>

2 局部组件

全局注册虽然很方便,但有使用起来会有几个问题:

  1. 全局注册在打包的时候都会被打在一个包中(这种情况叫“tree-shaking”),如果你注册了很多的全局组,即使它并没有被实际使用到,但是仍然会被打包在一个 JS 文件中,浏览器使用的时候一次全部加载进入缓存中来。
  2. 全局注册在大型项目中使项目的依赖关系变得复杂。在父组件中使用子组件时,不太容易定位到子组件的实现。和程序中使用过多的全局变量一样,这会影响整个项目代码的可维护性。

相比之下,局部注册的组件是在使用它的父组件中显式导入,并且只能在该父组件中使用。它的优点是使组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好。

App.vue中模板可以直接导入index.vue,将index.vue注册为它的子组件。

<script setup>
 import index from './components/index.vue';//导入组件index.vue
</script>
<template>
<index/>------------使用了全局组件index
</template>

5.2 Props

  Props作用是将字符串、数字、数组和对象等值从父组件传递给子组件。当你想到在 JavaScript 中传递参数的时候,首先想到的可能是使用函数传递参数,就像函数中使用arguments一样处理参数。在vue中Props也可以像arguments一样在组件间传值,两个父子组件通过 Props 传递参数。在 Props 传递参数的时候可以在组件内部设定一个初始化函数,对 Props中的参数进行一个初始化的预定处理。

  Vue.js 有一种机制,通过设置要传递的值的数据类型和默认值,使用 Props 将正确的数据传递给组件,以免导致错误。必须将正确的数据传递给组件,才能使组件正常工作。在路由的使用中就介绍过路由之间用Props如何传递参数,现在要介绍的组件之间如何使用Props。

在这里插入图片描述

5.2.1 组件之间如何传值

  让我们创建一个简单的例子,看看如何使用 props传递参数。首先在index.vue文件中进行修改,使用defineProps函数获得props中的参数用于接收和显示名称,defineProps函数中的参数类型为数组。

index.vue

在components目录中创建一个index.vue文件。

<script setup>
defineProps(['name']);
</script>
<template>
  <h1>{{ name }}</h1>
</template>
<style></style>

App.vue

在index组件中使用name属性设置一个字符串参数,将这个字符串传递给index.vue文件中的defineProps([‘name’]);函数,在模板将这个参数字符串显示出来。

<script setup>
import index from './components/index.vue';
</script>
<template>
<index name="我是一个Props 参数" />
</template>

在这里插入图片描述
组件可以重复使用传递不同的参数字符串。

<script setup>
import index from './components/index.vue';
</script>
<template>
<index name="我是一个Props 参数" />
<index name="我是二" />
<index name="我是三" />
</template>

5.2.2 参数绑定 v-bind

  很多情况下我们需要在script标签中定义参数,而这些script标签中的参数需要进行值传递。这种情况下会使用到v-bind 指令进行参数名称绑定。如果不使用v-bind 设置绑定,name属性中设置的字符串(“productName”)将原样传递这个字符串(“productName”)给子组件,而不是script中的productName对象。

App.vue

<script setup>
import index from './components/index.vue';
const productName="const传值";//传递的参数
</script>
<template>
//通过v-bind 指令绑定productName参数与name关系
<index v-bind:name="productName" />
<index name="我是一个Props 参数" />
<index name="我是二" />
<index name="我是三" />
</template>

ref 函数绑定

如果在 props 中传递的数据需要用户交互而发生变化,可以使用 ref 函数定义一个反应变量,并使用 v-bind 设置该变量。

<script setup>
import index from './components/index.vue';
import { ref } from 'vue';
const productName = ref('const 参数');
</script>
<template>
<index v-bind:name="productName" />
<index name="我是一个Props 参数" />
<index name="我是二" />
<index name="我是三" />
</template>

描述指令 v-bind:name,也可以使用缩写形式(语法糖):name来绑定。

5.2.3 参数类型

  上面的示例中对Props 参数使用的非常简单就是以字符串为参数进行值传递。Props也可以将字符串以外的任何内容作为要传递的值进行参数传递。但是,随着代码变得越来越复杂,很多时候我们可能会传递一个数字而不是字符串,或者传递一个Json对象。Props 中传入的这些不同类型的数据都会被defineProps函数接收与处理。

  在vue.js中为了定义不同类型的参数,可以通过defineProps函数中的type属性来设置props中输入了什么类型的值。例如下面中 index 组件的 props 名称中包含字符串,因此首先将类型设置为 String。String的首字母大写,小写会报错。这声明该name属性将包含一个 String(字符串)。id属性类型被定义为数字类型,type设置为 Number,这样代表id获得值为数字类型。

index.vue

  在index.vue组件中,获得来在父组件传递过来的参数,使用defineProps函数获得并且设置出这三个参数的数据类型。之前,我们只是用 props 设置数组并设置获得name属性。当我们需要设置不同属性的类型时候,可以参照下面的写法进行设置。

<script setup>
 //defineProps 接收父组件Props中的参数
 //设置name     字符串类型 type: String
 //设置id       数字类型   type: Number     
 //设置dept     对象类型   type: Object
const props =defineProps({
  name: {
    type: String,
  },
  id: {
    type: Number,
  },
  dept: {
    type: Object,
  },
});
</script>
<template>
  <h1>id:{{ id }}</h1>
  <h1>名称:{{ name }}</h1>
  <h1>部门:{{ dept.name }} 部门id:{{ dept.id }}</h1>
</template>
<style></style>

App.vue

  App.vue中的index组件绑定三个参数name,id,dept到props中。注意这里的dept属性实际上是一个对象类型。

<script setup>
import index from './components/index.vue';
import { ref } from 'vue';
const productName = ref('const 参数');
const dpet = ref({name:"部门一",id:"10"});
</script>
<template>
<index v-bind:name="productName" id="我不是数字" :dept="dpet"/>
<index name="我是一个Props 参数" />
</template>

在这里插入图片描述

参数类型一览

  • String

  • Number

  • Boolean

  • Array

  • Object

  • Date

  • Function

  • Symbol

类型不对发出警告

  让我们来看看如果props中定义的属性类型与传入的参数类型不对会发生什么?测试一下我们定义一个数子类型的参数,给它值传入一个字符类型,看看会有什么变化。

--------------------- index.vue ---------------------
<script setup>
 //defineProps 接收父组件Props中的参数
 //设置name     字符串类型 type: String
 //设置id       数字类型   type: Number     
 //设置dept     对象类型   type: Object
const props =defineProps({
  name: {
    type: String,
  },
  id: {
    type: Number,
  },
});
</script>
<template>
  <h1>id:{{ id }}</h1>
  <h1>名称:{{ name }}</h1>
</template>
<style></style>
--------------------- App.vue ---------------------
<script setup>
import index from './components/index.vue';
import { ref } from 'vue';
const productName = ref('const 参数');
</script>
<template>
<index v-bind:name="productName" id=“我不是数字”/>
<index name="我是一个Props 参数" />
</template>

在浏览器中会看到这个参数正常显示出来了,但是在控制台中会出现警告,我们会看到下面的警告内容。

在这里插入图片描述

控制台警告显示

  类型不对的时候会在控制台会出现一条警告,执行了类型检查并传递了一个数字而不是字符串。我们可以通过这条警告,来检查自己的代码中是否存在参数类型与参数不一致的情况。

5.2.4 props 默认与必填

在props对象的属性中可以设置这默认值,必添项。

1 默认值 default

  如果在子组件中调用的时候没有给props属性中的值传递任何参数的时候,这个时候props就会在配置中找到这个属性的默认值进行赋值。例如下面,默认值设置为“默认名字”。

defineProps({
  name: {
    type: String,
    default: '默认名字',
  },
});

index.vue组件中中如果设置了name属性的默认值,App.vue中如果没有为index组件设置name属性,将使用默认值。

<index name=“我是一个参数” />
<index />------------没有设置属性值,子组件中将显示默认值

组件部分将显示name属性的默认值“默认名字”。

在这里插入图片描述

如果我们在组件props的参数中没也有设置默认值会反生什么?

defineProps({
  name: {
    type: String,
  },
});

如果未设置默认值,控制台不会显示警告等消息。浏览器上没有显示任何内容,因为没有值通过 props 传递index 组件不会收到name参数的值。
在这里插入图片描述
2 设置必填项 Required

  required 属性来设置是否需是必填项。继续前面的内容,下面的例子让我们设置props属性内容为 required 而不设置 default 并且不在 component 标签中设置 props内容。required 的值可以是 true 或 false,我们将 prop 的中name属性设置为 required :true。

defineProps({
  name: {
    type: String,
    required: true,---必填项
  },
});

在浏览器控制台,将看到一条警告,指出即使这次需要该名称,也未提供该名称。警告说缺少道具“名称”
在这里插入图片描述
将 required 设置为 true 会导致显示警告, required 的默认情况为 false。

3 设置默认和必填项

  在项目开发中设置了default默认值,在组件中如果没有给props属性值,将会使用到默认值,所以不需要设置reuqired这个属性。换句话说,不需要像下面这样写 default 和 required 。

defineProps({
  name: {
    type: String,
    default: '默认名字',
    required: true,
  },
});

虽然此处设置了String的初始值,但设置数组或对象时可能会出现以下信息。

[Vue warn]: Invalid default value for prop "[props name]": Props with type Object/Array   must use a factory function to return the default value.

在这种情况下,您应该使用一个函数

defineProps({
  name: {
    type: String,
      default: () => [],
      default:[] //设置默认数组与对象
  },
});

5.2.5 验证设置

  现在我们轻松的理解了props中的类型、默认和必需的设置。但是我们还有一个重要的 Validation 功能没有介绍,下面让我们一起来深理解Validation使用。Validation主要的功能是验证和检查输入的值是否正确。在下面的例子中,来验证index组件name属性的值是否包含"默认名字", “zht”, "zhtbs"这几个字符串。如果不包含这些字符串,控制台发出警告。

index.vue

<script setup>
const props =defineProps({
  name: {
    type: String,
    default: '默认名字',
    //验证函数
    validator: (value) => {
        return ["默认名字", "zht", "zhtbs"].indexOf(value) !== -1;
      },
  }
});
</script>
<template>
  <h1>名称:{{ name }}</h1>
</template>
<style></style>

App.vue

<script setup>
import index from './components/index.vue';
</script>
<template>
<index name="我是一个参数" />
<index name="zhtbs" />
<index />
</template>

  由于验证器中指定的数组元素中不包含"我是一个参数",因此控制台日志中的消息将显示自定义验证器失败的警告。

在这里插入图片描述

  validator 我们来详细解释一下验证函数返回值,validator可以通过返回true或者false来判断成功或者失败,所以return true就一定会成功,当返回值被设置为 false 时,就会在控制台日志中收到警告。

<script setup>
const props =defineProps({
  name: {
    type: String,
    default: '默认名字',
    validator: (value) => {
        return false;//不管值是什么都会收到验证警告
      },
  }
});

  例如 对Props中接收到的值的字符串长度进行校验,可以这样写设置校验。如果字符数大于 6,此验证将为 true,因此如果您输入 3 个字符的包,它将为 false 并显示警告。

defineProps({
  name: {
    type: String,
    default: '默认名字',
    validator: (value) => {
	//验证name是否大于6个字符
      return value.length > 6;
    },
  },
});

  Slots也可以用在父组件与子组件的传值方面。Props 允许传递字符串、数字、数组和对象等参数,而 Slots 允许您传递 HTML 标签。为了更好的加深了对 Props 的理解,请在 Props 之后学习了解Slots 的使用。

5.2.6 useAttrs 属性设置

  在script setup中useAttrs 函数返回了 a t t r s 对象的引用。 attrs对象的引用。 attrs对象的引用。attrs对象保存了父组件模板中引用的子组件设置的class和style样式值,在把它们传回给子组件使用的一个通信工具类。在vue程序中会自动将组件中引用的子组件设置的class和style属性的值装入到 a t t r s 对象。 attrs对象。 attrs对象。attrs也会像props一样装入其他的参数属性,在子组件中这些被装入的其他参数也会被$attrs对象引用到。
在这里插入图片描述

App.vue

在使用到的子组件中,设置class属性和,id 和 style 参数值,它将会传递给子组件。

<script setup>
import index from './components/index.vue';
</script>
<template>
 <index id="main" style="color:red" class="active" />
</template>

index.vue

在子组件中通过useAttrs()获得attrs对象,将attrs对象中的class样式绑定到p标签中的class。

<script setup>
import { useAttrs } from 'vue';
const attrs = useAttrs();
console.log(attrs);
</script>
<template>
<p :class="attrs.class">class属性确认中</p>
</template>
<style></style>

浏览其中会看到字体变红,和attrs对象中的内容。

在这里插入图片描述

  但是我们会发现一个问题,就是attrs中的其他参数没有被绑定到模板元素上,这个时候它们都都会变成p标签中属性。

在这里插入图片描述

  我们来看修改一下index.vue中的代码,增加几个html标签在这些标签中使用useAttr对象中的属性。

<script setup>
import { useAttrs } from 'vue';
const attrs = useAttrs();
console.log(attrs);
</script>
<template>
  <p :class="attrs.class">class属性确认中</p>
  <h2 class="info">子页面</h2>
  <p :style="attrs.style">style属性确认中</p>
</template>
<style></style>

浏览器中显示结果。
在这里插入图片描述

我们会看到在多个html标签中useAttr对象中的值没有变成为这些html标签中的属性。

  • 当模板中只有一个html标签绑定attrs对象时候,attrs中所有的值都会成为这个html元素中的属性。
  • 当模板中多个htm标签绑定attrs对象,attrs对象中的值不会成为它们元素属性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1044812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

regexp 应用

今天同事拿出个小栗子 1 如果用like的话 1,22 的情况会被字符串2匹配到这样会有问题 这里需要用concat将uids处理下 比如第一条处理成&#xff0c;1,2&#xff0c;3&#xff0c; 的形式 去模糊匹配 ‘%,1,%’ 当然like这种模糊匹配不太建议使用 2 regexp 用法 单个值 &#x…

SpringBoot的excel模板导出

Word的模板导出(参考&#xff1a;https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill) 创建有两个sheet的excel文件模板 将模板文件放入resource\templates/doc下使用 public void exportUavInfoExcel(HttpServletResponse response, CaseExportRPO cas…

如何更改注册表使系统暂停更新时间延长

1、创建一个文本文件&#xff0c;命名为&#xff1a;“stopupdate.reg”&#xff0c;然后用记事本或者代码编辑器打开&#xff0c;复制以下代码&#xff1a; Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings] "F…

气传导耳机有哪些好处?热门气传导耳机推荐

​随着气传导耳机的快速发展&#xff0c;在运动、办公等场合能够经常看到&#xff0c;带来了前所未有的舒适体验。作为一种新型耳机类型&#xff0c;相较传统入耳式耳机来说&#xff0c;更有利于耳道卫生&#xff0c;在听歌时还能保持对环境声的感知。面对市面上这么多气传导耳…

Docker(二)、linux环境Docker的部署以及构建镜像

linux环境Docker的部署以及构建镜像 一、docker部署1、快速部署常用的命令&#xff1a;1.1、demo-部署tomcat1.2、tomcat容器内部结构1.2.1、每个tomcat容器&#xff0c;都包含三个组件1.2.2、在容器内部执行命令 1.3、容器生命周期 二、Dockerfile构建镜像1、demo-Dockerfile自…

[Linux入门]---进程优先级

文章目录 1.进程优先级基本概念 2.查看系统进程PRI and NI 3.查看进程优先级的命令引入其他概念 1.进程优先级 基本概念 cpu资源分配的先后顺序&#xff0c;就是指进程的优先权&#xff08;priority&#xff09;。优先权高的进程有优先执行权利。配置进程优先权对多任务环境的…

golang工程——常用数据结构底层原理【mao、slice、func、string】

字符串 其实就是字符数组 注意 字节数组与字符串可以相互转换 a : "hello world" b : []byte(a) c : string(b)字节数组转换为字符串在运行时调用了slicebytetostring函数。需要注意的是&#xff0c;字节数组与字符串的相互转换并不是简单的指针引用&#xff0c;…

下划线在键盘上怎么打?这3个方法快收藏!

“我最近的工作中好像很多文件里都有下划线&#xff0c;但是我不知道在键盘上应该怎么把下划线打出来&#xff0c;有没有知道的朋友呀&#xff1f;” 在计算机文档和编程中&#xff0c;下划线是一个常见的特殊字符。很多用户在使用电脑时可能也经常需要用到下划线。但是下划线在…

除静电离子风机在无尘车间的应用

除静电离子风机在无尘车间中的应用非常广泛&#xff0c;主要是用来控制车间内的静电荷&#xff0c;防止静电对车间内的电子元器件、电路板等敏感部件产生损害。 具体来说&#xff0c;除静电离子风机通常采用电离器产生大量负离子&#xff0c;将车间内的静电荷中和成无害的水蒸气…

基于微信小程序的高校学生事务考试通知管理系统(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

基于Java SpringBoot 的书籍学习平台,附源码,数据库

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 功能总览4平台设计4.1 平台功能模块设计4.2数据库设计4.2.1概念模型设计4.2.2物理…

100GBASE-DR光模块:高速数据中心互连的全新选择

100GBASE-DR光模块相较于传统的100G QSFP28光模块采用的是PAM4调制&#xff0c;单波长传输数据率更高&#xff0c;具有低功耗、高密度、高可靠性等优点&#xff0c;更适用于高速数据中心互连方案部署。本文将从100G QSFP28 DR光模块的概念界定、日常运行流程及其场景方案等角度…

ubuntu中的系统消息中显卡显示llvmpipe (LLVM 10.0.0, 256 bits)

这是我在使用ubuntu系统时出现的问题&#xff0c;网上搜到很多解决的办法&#xff0c;我是一顿操作&#xff0c;后来看到这位老哥的帖子解决了。 集Linux / Ubuntuwin10双系统安装记录(2):AMD核显驱动引发的问题 - 知乎上一篇中我们提到了 astroR2&#xff1a;Linux / Ubuntuw…

MySQL - group by分组查询 (查询操作 三)

功能介绍 group by: 对数据进行分组和聚合操作(可以操作单字段和多字段) having&#xff1a;过滤group by的结果&#xff0c;也就是在分组后添加筛选条件 基础语法 select 字段列表 from 表名 [ where 条件 ] group by 分组字段名 [ having ]; where 和 having的区…

【Visual Studio】解决编写C#代码时编辑器自动添加using问题

当我们编写引用其他作用域代码时&#xff0c;Visual Studio可能会非常“智能”地帮我们在代码顶部自动添加对应的using指令。 显然这项举动有利有弊&#xff0c;有利在于可以提高代码编写效率&#xff0c;有弊在于如果不慎编写错误的代码那么错误的using指令会自动添加。 尤其在…

核电厂设备故障预测与健康管理-基于PreMaint电气信号分析技术

核电厂作为重要的能源供应基地&#xff0c;设备的可靠性和安全性至关重要。传统的设备维护方式存在一定的盲目性和浪费&#xff0c;为了提高设备维护效率、减少成本&#xff0c;并确保核电厂的安全和稳定运行&#xff0c;引入了PreMaint设备健康管理平台的电气信号分析技术。本…

​比特币ETF将迎来审核窗口期

作者&#xff1a;Greg Cipolaro&#xff0c;NYDIG 全球研究主管 编译&#xff1a;WEEX Exchange 几只重要的 ETF 申请将于 10 月中旬迎来审核窗口&#xff0c;本文通过观察近期期权市场的动态&#xff0c;以研究交易者对这些关键 ETF 日期的仓位态度&#xff1b;门头沟&#xf…

当网络设置为自动获取dns时而实际nds是8.8.8.8,1.1.1.1的解决方法

笔记本换网络环境后&#xff0c;网络设置的是自动获取IP和自动获取dns。但使用命令&#xff1a;config/all命令时发现dns总是8.8.8.8,1.1.1.1。导致csdn上不了。 8.8.8.8,1.1.1.1&#xff1a;是谷歌的dns。 解决办法&#xff1a; 在支行中输入regedit打开注册表后&#xff0…

火狐连接错误代码SEC_ERROR_UNKNOWN_ISSUER

最近开发的实验启动功能&#xff0c;测试人员用火狐浏览进行测试&#xff0c;一直报错 错误代码SEC_ERROR_UNKNOWN_ISSUER 在网上搜索很多文章&#xff0c;都没有解决我的问题&#xff0c;最后自己花时间研究了下&#xff0c;灵感来源于项目中&#xff0c;就类似于白名单的功能…

DragGesture/拖动手势 的使用

1. DragGesture 拖动手势操作 1.1 实现 /// 拖动手势 struct DragGestureBootcamp: View {State var offset: CGSize .zerovar body: some View {//dragGesture1dragGesture2}/// 方式二var dragGesture2: some View{ZStack {VStack {Text("\(offset.width)")Space…