前言
如何在有一定vue基础的前提下,进一步的提示自己的vue呢?如何能写出更加完美的组件呢?学习别人的优秀代码就是很不错的一种方式。Element Plus无疑是很不错的一个学习资源,除了可以好好学习vue3,顺便还能学习一下ts。
button
el-button
的底层是基于原生button
进行封装的。说的原生button
,才发现自己好像真的不怎么熟悉,如果跟我一样的话,可以看一下 HTML <button> 标签
定义
<button>
标签定义一个按钮。`在 button 元素内部,您可以放置内容,比如文本或图像。
重要属性
属性 | 值 | 描述 |
disabled | disabled | 规定应该禁用该按钮 |
name | button_name | 规定按钮的名称 |
type | button、reset、submit | 规定按钮的类型 |
知识点
注: 就简单学习一下个人觉得比较重要的地方,就只考虑button
,不考虑其他内容。
1、类型别名
//类型别名
export type ButtonType = "default" | "primary";
类型别名一般用于给一个联合类型取新的名字,对代码的整洁还是有很大的帮助
2、PropType
import type { PropType } from 'vue'
Vue 对定义了 type 的 prop 执行运行时验证。要将这些类型提供给 TypeScript,我们需要使用 PropType 指明构造函数。
3、指定并校验props属性
// 引入自定义的类型
import type {ButtonType} from "./ts/type";
// 按钮类型
type: {
type: String as PropType<ButtonType>,
default: "default",
validator: (val: string) => {
return ["default", "primary"].includes(val);
},
},
validator:Function 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。
4、类型断言
// 将一个父类断言为更加具体的子类
type: String as PropType<ButtonType>,
- 将一个联合类型断言为其中一个类型
- 将一个父类断言为更加具体的子类
- 将任何一个类型断言为any
- 将any断言为一个具体的类型
5、插槽
<span v-if="$slots.default"><slot></slot></span>
这个之前没接触过,查了一下,$slots官方解释:
default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容。
大体就是插槽内除了具名插槽(不包括default)的内容,比如:
<div>
<!-- 具名插槽 -->
<template v-solt="name">
<div></div>
</template>
<!-- 剧名插槽外的内容 -->
<div>aaa</div>
</div>
6、emit
emits: ['click'],
const handleClick = (evt: MouseEvent) => {
emit('click', evt)
}
因为按钮本身就存在单击事件,因此最后还是执行的单击事件。
简单demo
<template>
<button
:class="[
'base-button',
type ? type : 'default',
disabled ? 'disabled' : ''
]"
disabled
@click="handleClick"
>
<span v-if="$slots.default">
<slot></slot>
</span>
</button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import type { PropType } from "vue";
// 引入自定义的类型
import type { ButtonType } from "./type";
export default defineComponent({
name: 'YcButton',
props: {
// 按钮类型
type: {
type: String as PropType<ButtonType>,
default: "default",
validator: (val: string) => {
return ["default", "primary"].includes(val);
},
},
//是否禁用
disabled: {
type: Boolean,
default: false
},
icon: {
type: String,
default: ''
}
},
emits: ['click'],
setup(props, { emit }) {
const handleClick = (evt: MouseEvent) => {
emit('click', evt)
}
return {
handleClick
}
}
});
</script>
<style scoped lang="scss">
.base-button {
padding: 10px 15px;
cursor: pointer;
border-radius: 5px;
font-size: 14px;
font-family: "hyjt";
}
.primary {
background: #409eff;
border: 1px solid #dcdfe6;
color: #ffffff;
}
.default {
background: #ffffff;
border: 1px solid #dcdfe6;
color: #606266;
}
.disabled {
background: #a0cfff;
cursor: not-allowed;
}
</style>
效果
上面那个是我自己写的,下面这个是el-button
,不考虑其他东西,感觉还可以😁