Vue.js组件精讲 第2章 基础:Vue.js组件的三个API:prop、event、slot

如果您已经对 Vue.js 组件的基础用法了如指掌,可以跳过本小节,不过当做复习稍读一下也无妨。

组件的构成

一个再复杂的组件,都是由三部分组成的:prop、event、slot,它们构成了 Vue.js 组件的 API。如果你开发的是一个通用组件,那一定要事先设计好这三部分,因为组件一旦发布,后面再修改 API 就很困难了,使用者都是希望不断新增功能,修复 bug,而不是经常变更接口。如果你阅读别人写的组件,也可以从这三个部分展开,它们可以帮助你快速了解一个组件的所有功能。

属性 prop

prop 定义了这个组件有哪些可配置的属性,组件的核心功能也都是它来确定的。写通用组件时,props 最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性的值,这点在组件开发中很重要,然而很多人却忽视,直接使用 props 的数组用法,这样的组件往往是不严谨的。比如我们封装一个按钮组件 <i-button>

<template><button :class="'i-button-size' + size" :disabled="disabled"></button>
</template>
<script>// 判断参数是否是其中之一function oneOf (value, validList) {for (let i = 0; i < validList.length; i++) {if (value === validList[i]) {return true;}}return false;}export default {props: {size: {validator (value) {return oneOf(value, ['small', 'large', 'default']);},default: 'default'},disabled: {type: Boolean,default: false}}}
</script>

使用组件:

<i-button size="large"></i-button>
<i-button disabled></i-button>

组件中定义了两个属性:尺寸 size 和 是否禁用 disabled。其中 size 使用 validator 进行了值的自定义验证,也就是说,从父级传入的 size,它的值必须是指定的 small、large、default 中的一个,默认值是 default,如果传入这三个以外的值,都会抛出一条警告。

要注意的是,组件里定义的 props,都是单向数据流,也就是只能通过父级修改,组件自己不能修改 props 的值,只能修改定义在 data 里的数据,非要修改,也是通过后面介绍的自定义事件通知父级,由父级来修改。

在使用组件时,也可以传入一些标准的 html 特性,比如 id、class:

<i-button id="btn1" class="btn-submit"></i-button>

这样的 html 特性,在组件内的 <button> 元素上会继承,并不需要在 props 里再定义一遍。这个特性是默认支持的,如果不期望开启,在组件选项里配置 inheritAttrs: false 就可以禁用了。

插槽 slot

如果要给上面的按钮组件 <i-button> 添加一些文字内容,就要用到组件的第二个 API:插槽 slot,它可以分发组件的内容,比如在上面的按钮组件中定义一个插槽:

<template><button :class="'i-button-size' + size" :disabled="disabled"><slot></slot></button>
</template>

这里的 <slot> 节点就是指定的一个插槽的位置,这样在组件内部就可以扩展内容了:

<i-button>按钮 1</i-button>
<i-button><strong>按钮 2</strong>
</i-button>

当需要多个插槽时,会用到具名 slot,比如上面的组件我们再增加一个 slot,用于设置另一个图标组件:

<template><button :class="'i-button-size' + size" :disabled="disabled"><slot name="icon"></slot><slot></slot></button>
</template>
<i-button><i-icon slot="icon" type="checkmark"></i-icon>按钮 1
</i-button>

这样,父级内定义的内容,就会出现在组件对应的 slot 里,没有写名字的,就是默认的 slot。

在组件的 <slot> 里也可以写一些默认的内容,这样在父级没有写任何 slot 时,它们就会出现,比如:

<slot>提交</slot>

自定义事件 event

现在我们给组件 <i-button> 加一个点击事件,目前有两种写法,我们先看自定义事件 event(部分代码省略):

<template><button @click="handleClick"><slot></slot></button>
</template>
<script>export default {methods: {handleClick (event) {this.$emit('on-click', event);}}}
</script>

通过 $emit,就可以触发自定义的事件 on-click ,在父级通过 @on-click 来监听:

<i-button @on-click="handleClick"></i-button>

上面的 click 事件,是在组件内部的 <button> 元素上声明的,这里还有另一种方法,直接在父级声明,但为了区分原生事件和自定义事件,要用到事件修饰符 .native,所以上面的示例也可以这样写:

<i-button @click.native="handleClick"></i-button>

如果不写 .native 修饰符,那上面的 @click 就是自定义事件 click,而非原生事件 click,但我们在组件内只触发了 on-click 事件,而不是 click,所以直接写 @click 会监听不到。

组件的通信

一般来说,组件可以有以下几种关系:

在这里插入图片描述

A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代关系(可能隔多代)。组件间经常会通信,Vue.js 内置的通信手段一般有两种:

  • ref:给元素或组件注册引用信息;
  • $parent / $children:访问父 / 子实例。

这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据,比如下面的示例中,用 ref 来访问组件(部分代码省略):

// component-a
export default {data () {return {title: 'Vue.js'}},methods: {sayHello () {window.alert('Hello');}}
}
<template><component-a ref="comA"></component-a>
</template>
<script>export default {mounted () {const comA = this.$refs.comA;console.log(comA.title);  // Vue.jscomA.sayHello();  // 弹窗}}
</script>

$parent 和 $children 类似,也是基于当前上下文访问父组件或全部子组件的。

这两种方法的弊端是,无法在跨级或兄弟间通信,比如下面的结构:

// parent.vue
<component-a></component-a>
<component-b></component-b>
<component-b></component-b>

我们想在 component-a 中,访问到引用它的页面中(这里就是 parent.vue)的两个 component-b 组件,那这种情况下,就得配置额外的插件或工具了,比如 Vuex 和 Bus 的解决方案,本小册不再做它们的介绍,读者可以自行阅读相关内容。不过,它们都是依赖第三方插件的存在,这在开发独立组件时是不可取的,而在小册的后续章节,会陆续介绍一些黑科技,它们完全不依赖任何三方插件,就可以轻松得到任意的组件实例,或在任意组件间进行通信,且适用于任意场景。

结语

本小节带您复习了 Vue.js 组件的核心知识点,虽然这并没有完全覆盖 Vue.js 的 API,但对于组件开发来说已经足够了,后续章节也会陆续扩展更多的用法。

基于 Vue.js 开发独立组件,并不是新奇的挑战,坦率地讲,它本质上还是 JavaScript。掌握了 Vue.js 组件的这三个 API 后,剩下的便是程序的设计。在组件开发中,最难的环节应当是解耦组件的交互逻辑,尽量把复杂的逻辑分发到不同的子组件中,然后彼此建立联系,在这其中,计算属性(computed)和混合(mixins)是两个重要的技术点,合理利用,就能发挥出 Vue.js 语言的最大特点:把状态(数据)的维护交给 Vue.js 处理,我们只专注在交互上。

当您最终读完本小册时,应该会总结出和笔者一样的感悟:Vue.js 组件开发,玩到最后还是在拼 JavaScript 功底。对于每一位使用 Vue.js 的开发者来说,阅读完本小册都可以尝试开发和维护一套属于自己的组件库,并乐在其中,而且你会越发觉得,一个组件或一套组件库,就是融合了前端精髓的产出。

扩展阅读

  • Vue 组件通信之 Bus
  • Vuex通俗版教程

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

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

相关文章

科研学习|可视化——Origin绘制相关性系数矩阵

一、Origin软件版本 Origin2021版本 二、插件下载地址 CorrelationPlot.opx资源-CSDN文库 三、插件安装步骤 从上述链接下载插件将插件解压缩&#xff08;最好是解压缩到orgin的安装目录&#xff09;用origin打开插件&#xff08;或者打开origin&#xff0c;将插件拖拽到origin…

STL--vector

目录 【本节目标】 1.vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用及底层模拟实现 vector类中成员变量 1.2.1 vector的定义 1.2.2 vector iterator 的使用 1.2.3 vector 空间增长问题 1.2.3 vector 增删查改 1.2.4 vector 迭代器失效问题 1.2.5 使用memcp…

git工具上传文件超过100MB解决方法

Github 上传超过100M的大文件 - 简书 (jianshu.com) 看到一个不错的贴子。 29660DESKTOP-CAB6SQB MINGW64 /d/predict-system $ git init Initialized empty Git repository in D:/predict-system/.git/29660DESKTOP-CAB6SQB MINGW64 /d/predict-system (master) $ git lfs tr…

基于java+springboot+vue实现的居家养老健康管理系统(文末源码+Lw)23-313

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装智慧社区居家养老健康管理系统软件来发挥其高效地信息处理…

设计模式-享元模式(Flyweight)

1. 概念 享元模式是一种结构型设计模式&#xff0c;它通过共享技术有效地支持大量细粒度对象的复用。 2. 原理结构图 图1 图2 2. 1 角色 抽象享元&#xff08;Flyweight&#xff09;&#xff1a;这是所有具体享元类的基类&#xff0c;它定义了享元对象的内部状态和外部状…

java快速幂算法

快速幂算法 参考视频(参考五角七边up大佬&#xff09; 幂运算的介绍 幂运算是指将一个数自身乘以自身多次的运算&#xff0c;其表达式为 a n a^n an&#xff0c;其中 a a a 是底数&#xff0c; n n n 是指数。 快速幂解释 快速幂算法是一种用于快速计算幂运算的算法&…

[当人工智能遇上安全] 13.威胁情报实体识别 (3)利用keras构建CNN-BiLSTM-ATT-CRF实体识别模型

《当人工智能遇上安全》系列将详细介绍人工智能与安全相关的论文、实践&#xff0c;并分享各种案例&#xff0c;涉及恶意代码检测、恶意请求识别、入侵检测、对抗样本等等。只想更好地帮助初学者&#xff0c;更加成体系的分享新知识。该系列文章会更加聚焦&#xff0c;更加学术…

Unity中支持泰语--没有版权限制

在Unity中支持泰语主要涉及以下几个方面&#xff1a; 选择合适的字体&#xff1a;在Unity中&#xff0c;确保使用支持泰文字符的字体是至关重要的。例如&#xff0c;可以选择使用Noto Serif Thai字体&#xff0c;这是一个支持泰语的字体2。 处理Unity版本问题&#xff1a;某些…

CentOS 网卡ifcfg-eth0 ping不通外网(www.baidu.com)

1、如果确认好就直接激活网卡&#xff01; ifup eth0 2、慢慢找&#xff1a; cd /etc/sysconfig/network-scripts/ ls 找到你的网卡是啥&#xff0c;这里网卡是 ifcfg-eth0 执行1就好了&#xff01;

JetBrains PyCharm 2024.1 发布 - 面向专业开发者的 Python IDE

JetBrains PyCharm 2024.1 发布 - 面向专业开发者的 Python IDE 请访问原文链接&#xff1a;JetBrains PyCharm 2024.1 (macOS, Linux, Windows) - 面向专业开发者的 Python IDE&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org…

acwing2060. 奶牛选美

题目&#xff1a; 代码&#xff1a; //acwing2060. 奶牛选美 #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N55; const int dx[]{-1,0,1,0},dy[]{0,-1,0,1}; bool st[N][N]; int point[N][N]; char map[N][…

MYBATIS获取参数值

MYBATIS最核心的莫过于动态的获取各种的参数值, 为了将来更好的使用MYBATIS进行开发, 我们必须先打好 "获取参数值" 这一基础 一. MYBATIS获取参数值的两种情况: 1.${} 实质:字符串的拼接 注解:${}使用的字符串拼接的方式拼接SQL语句, 所以, 如果其中出现了字符串…

APP下载页前端自适应HTML源码

源码介绍 APP下载页前端自适应HTML源码&#xff0c;可以作为自己的软件介绍页或者app下载页&#xff0c;喜欢的朋友可以拿去研究 效果预览 HTML源码下载 https://www.qqmu.com/3026.html

Flink WordCount实践

目录 前提条件 基本准备 批处理API实现WordCount 流处理API实现WordCount 数据源是文件 数据源是socket文本流 打包 提交到集群运行 命令行提交作业 Web UI提交作业 上传代码到gitee 前提条件 Windows安装好jdk8、Maven3、IDEA Linux安装好Flink集群&#xff0c;可…

Java并发(1)--线程,进程,以及缓存

线程和进程是什么&#xff1f; 进程 进程是程序的一次执行过程&#xff0c;系统程序的基本单位。有自己的main方法&#xff0c;并且主要由主方法运行起来的基本上就是进程。 线程 线程与进程相似&#xff0c;但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以…

MVCC(解决MySql中的并发事务的隔离性)

MVCC 如何保证事务的隔离性&#xff1f; 1.排他锁&#xff1a;如一个事务获取了一个数据行的排他锁&#xff0c;其他事务就不能再获取改行的其他锁。 2.MVCC&#xff1a;多版本并发控制。 MVCC&#xff1a; 1.隐藏字段 1.DB_TRX_ID&#xff1a;最近修改事务的id。默认值从0开…

【MYSQL】索引机制概述

由于MySQL是作为存储层部署在业务系统的最后端&#xff0c;所有的业务数据最终都要入库落盘&#xff0c;但随着一个项目在线上运行的时间越来越久&#xff0c;数据库中的数据量自然会越来越多&#xff0c;而数据体积出现增长后&#xff0c;当需要从表查询一些数据时&#xff0c…

javaScript设计模式之简单工厂模式

简单工厂模式(Simple Factory):又叫静态工厂方法&#xff0c;由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。 场景一 假设我们需要计算圆形和矩形的面积 function Circle(radius) {this.radius radius;}Circle.prototype.getArea function() {re…

总结SQL相对常用的几个字符函数

目录 字符的截取 substr() trim()、ltrim()、rtrim() 字符串的拼接 ||、 字符的大小写转换 upper(column_name):大写 lower(column_name):小写 字符替换 replace() 搜索字符 instr(column_name, substring_to_find,start,n_appearence) charindex(substring_to_fi…

【问题解决】ubuntu安装新版vscode报code-insiders相关错误

问题 目前 vscode官网 最新的包为 insiders_1.89.0-1712297812_amd64.deb &#xff0c;双击或者使用sudo dpkg -i code-insiders_1.89.0-1712297812_amd64.deb安装后报错&#xff0c;执行其他命令也报错。 安装环境&#xff1a;ubuntu18.04 dpkg: 处理软件包 code-insiders (…