vue3-深入组件-组件注册和props更多细节

组件注册

定义好的组件需要注册才能被使用。 注册方式有两种

  1. 全局注册

  2. 局部注册

全局注册

.component() 方法,让组件在当前 Vue 应用中全局可用。 在 main.ts 中

import './assets/main.css'import { createApp } from 'vue'
import { createPinia } from 'pinia'
import GlobalTitle from '@/components/GlobalTitle.vue'import App from './App.vue'
import router from './router'const app = createApp(App)app.component('GlobalTitle', GlobalTitle)app.use(createPinia())
app.use(router)app.mount('#app')

在 vue 中直接使用无需导入

<script lang="ts" setup>
import { ref } from 'vue'
</script><template><div class="container"><GlobalTitle></GlobalTitle></div>
</template><style lang="scss" scoped>
.container {
}
</style>

效果:

全局注册的组件可以在此应用的任意组件的模板中使用,所有的子组件也可以使用全局注册的组件。

全局组件缺点

  • 全局注册,但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。

  • 全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性。

局部注册

局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用。

它的优点是使组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好。

定义组件

<script lang="ts" setup>
import { ref } from 'vue'
</script><template><div class="container"><h2>这是一个局部组件</h2></div>
</template><style lang="scss" scoped>
.container {
}
</style>

局部使用组件

<script lang="ts" setup>
import { ref } from 'vue'
import PartTitle from '@/components/PartTitle.vue'
</script><template><div class="container"><PartTitle /></div>
</template><style lang="scss" scoped>
.container {
}
</style>

组件名格式

推荐 PascalCase 作为组件名的注册格式。

  1. PascalCase 是合法的 JavaScript 标识符。这使得在 JavaScript 中导入和注册组件都很容易,同时 IDE 也能提供较好的自动补全。

  2. <PascalCase /> 在模板中更明显地表明了这是一个 Vue 组件,而不是原生 HTML 元素。同时也能够将 Vue 组件和自定义元素 (web components) 区分开来。

在单文件组件和内联字符串模板中,我们都推荐这样做。

为了方便,Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。

这意味着一个以 MyComponent 为名注册的组件,在模板中可以通过 <MyComponent> 或 <my-component> 引用。这让我们能够使用同样的 JavaScript 组件注册代码来配合不同来源的模板。

props

Props 声明

一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute。

setup 写法

组件定义

<script lang="ts" setup>
import { ref } from 'vue'const props = defineProps(['person'])
</script><template><div class="container"><h1>{{ props.person }}</h1></div>
</template><style lang="scss" scoped>
.container {
}
</style>

组件使用

<script lang="ts" setup>
import { ref } from 'vue'
import Com14 from '@/components/Com14.vue'
</script><template><div class="container"><Com14 person="'王大可'" /></div>
</template><style lang="scss" scoped>
.container {
}
</style>

声明对象形式的属性 setup JavaScript 形式

defineProps({title: String,likes: Number
})

setup TypeScript 形式

<script setup lang="ts">
defineProps<{title?: stringlikes?: number
}>()
</script>

对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告。

传递 prop 的细节

Prop 属性命名

如果一个 prop 的名字很长,应使用 camelCase 形式,因为它们是合法的 JavaScript 标识符

defineProps({greetingMessage: String
})<span>{{ greetingMessage }}</span>//推荐写法
<MyComponent greeting-message="hello" />
//或者
<MyComponent greetingMessage="hello" />

模版上使用属性则通常会将其写为 kebab-case 形式,这样和 HTML attribute 写法就一致了。

静态 vs. 动态 Prop

简单讲 就是传入数值是字符串还是变量

//这是静态
<Com14 person="王大可" />
//这是动态
<Com14 :person="personName" />
使用一个对象绑定多个 prop

v-bind 直接绑定对象,即只使用 v-bind 而非某一个属性

const post = {
id: 1,
title: 'My Journey with Vue'
}<BlogPost v-bind="post" />
// 实际等价于
<BlogPost :id="post.id" :title="post.title" />
单向数据流
  1. 所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。

  2. 这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

  3. 每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告:

const props = defineProps(['foo'])// ❌ 警告!prop 是只读的!
props.foo = 'bar'

「更改 props 的场景:」

prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。

在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可

const props = defineProps(['initialCounter'])// 计数器只是将 props.initialCounter 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
const counter = ref(props.initialCounter)

需要对传入的 prop 值做进一步的转换。

在这种情况中,最好是基于该 prop 值定义一个计算属性:

const props = defineProps(['size'])// 该 prop 变更时计算属性也会自动更新
const normalizedSize = computed(() => props.size.trim().toLowerCase())
Prop 校验
  1. Vue 组件可以更细致地声明对传入的 props 的校验要求。

  2. 比如我们上面已经看到过的类型声明,如果传入的值不满足类型要求,Vue 会在浏览器控制台中抛出警告来提醒使用者。

defineProps({// 基础类型检查// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)propA: Number,// 多种可能的类型propB: [String, Number],// 必传,且为 String 类型propC: {type: String,required: true},// Number 类型的默认值propD: {type: Number,default: 100},// 对象类型的默认值propE: {type: Object,// 对象或数组的默认值// 必须从一个工厂函数返回。// 该函数接收组件所接收到的原始 prop 作为参数。default(rawProps) {return { message: 'hello' }}},// 自定义类型校验函数// 在 3.4+ 中完整的 props 作为第二个参数传入propF: {validator(value, props) {// The value must match one of these stringsreturn ['success', 'warning', 'danger'].includes(value)}},// 函数类型的默认值propG: {type: Function,// 不像对象或数组的默认,这不是一个// 工厂函数。这会是一个用来作为默认值的函数default() {return 'Default function'}}
})

defineProps() 宏中的参数不可以访问 <script setup> 中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中。

额外说明:

  • 所有 prop 默认都是可选的,除非声明了 required: true

  • 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined。

  • Boolean 类型的未传递 prop 将被转换为 false。这可以通过为它设置 default 来更改——例如:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致。

  • 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。

当 prop 的校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)。

运行时类型检查

校验选项中的 type 可以是下列这些原生构造函数:

  • String

  • Number

  • Boolean

  • Array

  • Object

  • Date

  • Function

  • Symbol

type 也可以是自定义的类或构造函数,Vue 将会通过 instanceof 来检查类型是否匹配。

class Person {constructor(firstName, lastName) {this.firstName = firstNamethis.lastName = lastName}
}defineProps({author: Person
})

Vue 会通过 instanceof Person 来校验 author prop 的值是否是 Person 类的一个实例。

Boolean 类型转换
  1. 组件属性使用 Boolean 类型

defineProps({disabled: Boolean
})<!-- 等同于传入 :disabled="true" -->
<MyComponent disabled /><!-- 等同于传入 :disabled="false" -->
<MyComponent />
  1. prop 被声明为允许多种类型时

只有当 Boolean 出现在 String 之前时,Boolean 转换规则才适用

// disabled 将被转换为 true
defineProps({disabled: [Boolean, Number]
})// disabled 将被转换为 true
defineProps({disabled: [Boolean, String]
})// disabled 将被转换为 true
defineProps({disabled: [Number, Boolean]
})// disabled 将被解析为空字符串 (disabled="")
defineProps({disabled: [String, Boolean]
})

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+vue的网上租赁系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测,预测新数据

碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测&#xff0c;预测新数据 目录 碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测&#xff0c;预测新数据预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现LSTM长短期记忆神经网络多输入单输出未来…

架构师之路(十六)计算机网络(传输层)

前置知识&#xff08;了解&#xff09;&#xff1a;计算机基础。 作为架构师&#xff0c;我们所设计的系统很少为单机系统&#xff0c;因此有必要了解计算机和计算机之间是怎么联系的。局域网的集群和混合云的网络有啥区别。系统交互的时候网络会存在什么瓶颈。 既然网络层已经…

C# Bitmap类学习1

Bitmap对象封装了GDI中的一个位图&#xff0c;此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using …

mybatis----小细节

1、起别名 在MyBatis中&#xff0c;<typeAliases>元素用于定义类型别名&#xff0c;它可以将Java类名映射为一个更简短的别名&#xff0c;这样在映射文件中可以直接使用别名而不需要完整的类名。 下面是一个示例&#xff1a; 在mybatis核心配置文件中配置typeAliases标…

第21课 在Android Native开发中架起java与c++互通的桥梁

在开始本节课&#xff0c;我尝试把项目拷贝到另一台电脑上以便继续工作&#xff0c;但出现了大量的“could not be resolved”问题&#xff0c;尝试包含新的include路径也无法解决该问题&#xff0c;最后删除了项目的Native Support&#xff0c;然后重新添加Native Support才解…

百科同名就不能重建一个百科吗,代创建百科公司是如何做到的

发现自己的名字在百度上已经有百科词条并不出奇&#xff0c;因为同名同姓的人非常多&#xff0c;但是是不是百科已经有同名词条了就不能重建一个百科&#xff0c;很多朋友在自己做百度百科不通过时往往会发出这样的疑问。 实际上百度百科同名也是可以再重新创建的&#xff0c;…

【K8S】Service使用NodePort对外暴露应用

一、背景介绍 Pod是有生命周期的&#xff0c;当一个工作节点(node)销毁时&#xff0c;节点上运行的pods也会被销毁。ReplicationController会动态地在其他节点上创建Pod来保持应用程序的运行&#xff0c;每一个Pod都有一个独立的IP地址&#xff0c;甚至是同一个节点上的Pod。可…

菜鸟导入导出assetbundle

因为菜鸟不会用unity c#什么的&#xff0c;所以最后参考贴吧的方法用的是UABE(Unity Assets Bundle Extractor)和UABEA(Unity Assets Bundle Extractor Avalonia) 可以去github上下载 对于txt、xml什么的可以直接改&#xff0c;但是byte文件里还是会有一些类似乱码的东西&…

oracle vm安装ubuntu使用桥接网络不能访问外网

1. 问题描述 公司网络环境中&#xff0c;可以ping通内网中的所有电脑&#xff0c;ping不通百度域名以及百度的ip地址在热点共享时或者家里未出现此问题 2. 尝试的解决办法 设置网络共享&#xff0c;未起作用。后来测试通以后发现共享不共享都可以通 3. 最终解决办法 H3C禁…

案例需求:多人聊天室

文章目录 案例需求描述 p189使用wxPython绘制客户端界面 p190 案例需求描述 p189 图形界面的第三方库 使用wxPython绘制客户端界面 p190 代码示例&#xff1a; import wxclass YsjClient(wx.Frame):def __init__(self,client_name):# 调用父类的初始化方法# None&#xff1a;…

Linux——系统简介

1、从UNIX到LINUX 在目前主流的服务器端操作系统中&#xff0c;UNIX诞生于20世纪60年代末&#xff0c;Windows诞生于20世纪80年代中期&#xff0c;Linux诞生于20世纪90年代初&#xff0c;可以说UNIX是操作系统中的“老大哥”。 1.1、Linux简史 Linux内核最初是由李纳斯托瓦兹…

计算CNN卷积层和全连接层的参数量

计算CNN卷积层和全连接层的参数量 先前阅读 CNN ExplainerA Comprehensive Guide to Convolutional Neural Networks — the ELI5 way 本文主旨意在搞明白2个问题&#xff1a; 第一个问题 一个卷积操作&#xff0c;他的参数&#xff0c;也就是我们要训练的参数&#xff0c;也…

一种解决常用存储设备无法被电脑识别的方法

一、通用串行总线控制器描述 通用串行总线&#xff08;Universal Serial Bus&#xff0c;简称USB&#xff09;&#xff0c;是连接电脑与设备的一种序列总线标准&#xff0c;也是一种输入输出&#xff08;I/O&#xff09;连接端口的技术规范&#xff0c;广泛应用于个人电脑和移动…

香港高才通计划申请去年超3000万被拒!聊聊背后真实原因!

香港高才通计划申请去年超3000万被拒&#xff01;聊聊背后真实原因&#xff01; 香港高才通最新消息&#xff0c;截至2023年12月底&#xff0c;港府共收到64,820宗申请&#xff0c;当中近51,000宗获批。 具体各类申请的获批详情没有公布&#xff0c;知道的是&#xff0c;超过70…

postgresql12表膨胀解决(不锁表)

查看所有数据库占用磁盘空间 SELECTpg_database.datname AS "数据库名称",pg_size_pretty(pg_database_size(pg_database.datname)) AS "磁盘占用空间" FROMpg_database;发现有个数据库占用空间过大 查询库中所有表占用空间 SELECTtable_name,pg_size_…

Leetcode1143. 最长公共子序列

解题思路 求两个数组或者字符串的最长公共子序列问题&#xff0c;肯定是要用动态规划的。下面的题解并不难&#xff0c;你肯定能看懂。 首先&#xff0c;区分两个概念&#xff1a;子序列可以是不连续的&#xff1b;子数组&#xff08;子字符串&#xff09;需要是连续的&#xf…

JVM篇--垃圾回收器高频面试题

1 你知道哪几种垃圾收集器&#xff0c;各自的优缺点是啥&#xff0c;重点讲下cms和G1&#xff0c;包括原理&#xff0c;流程&#xff0c;优缺点&#xff1f; 1&#xff09;首先简单介绍下 有以下这些垃圾回收器 Serial收集器&#xff1a; 单线程的收集器&#xff0c;收集垃圾时…

Unity中UGUI在Mask剪裁粒子特效的实现

在Unity使用Mask是剪裁不了粒子特效的&#xff0c;之前有想过RenderTexture来实现&#xff0c;不过使用RenderTexture不适合用于很多个特效&#xff0c;因为RenderTexture依赖Camera的照射&#xff0c;如果在背包中每种道具都有不同的特效&#xff0c;那使用RenderTexture则需要…

PySide6/PyQt6中Qt窗口标志/窗口属性汇总,如何正确的设置窗口标志/窗口属性

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📚 窗口标志汇总📚 窗口属性汇总📝 使用方法📝 注意事项⚓️ 相关链接 ⚓️📖 介绍 📖 在Qt框架中,窗口标志(window flags)是用于控制窗口的各种属性和行为的强大工具。它们通过设置窗口的属性,如边框…