Element Plus 组件库实现:1. 实现Button(简易版)

Button------按钮组件

需求分析

Button组件是我们平时用到的比较多的一个组件,那么我们先来看一下Button是怎么实现的。由于HTML给我们提供了<button>标签,所以本次实现Button组件也是基于原生的<button>来实现。

Button属性

在使用Button时,我们大部分关注的是样式的选择,所以实现一个Button组件,更多关注的是怎么给组件添加相应的样式,那么这时就可以通过给组件添加不同的属性进而动态的添加class以实现不同样式的按钮:

ts 复制代码
// types.ts

// 类型
export type ButtonType = "primary" | "success" | "warning" | "danger" | "info";
// 尺寸
export type ButtonSize = "large" | "small";
// 为了和Form表单结合使用
export type NativeType = "button" | "submit" | "reset";

export interface ButtonProps {
  type?: ButtonType;
  size?: ButtonSize;
  // 朴素类型
  plain?: boolean;
  // 圆角型
  round?: boolean;
  // 圆形
  circle?: boolean;
  // 禁用状态
  disabled?: boolean;
  nativeType?: NativeType;
  // 原生 `autofocus` 属性
  autofocus?: boolean;
  // 加载中
  loading?: boolean;
  // 带icon的Button
  icon?: string;
}
// 组件实例
export interface ButtonInstance {
  ref: HTMLButtonElement;
}

组件实现

html 复制代码
// Button.vue

<script setup lang="ts">
import { ref } from 'vue';
import type { ButtonProps } from './types';
import Icon from '../Icon/Icon.vue'
defineOptions({
    name: 'YvButton'
})
withDefaults(defineProps<ButtonProps>(), {
    nativeType: 'button'
})
const _ref = ref<HTMLButtonElement>()
// 暴露组件属性以及方法,以便外部使用
defineExpose({
    ref: _ref
})
</script>

<template>
    <button ref="_ref" class="yv-button" :class="{
        [`yv-button--${type}`]: type,
        [`yv-button--${size}`]: size,
        'is-plain': plain,
        'is-round': round,
        'is-circle': circle,
        'is-disabled': disabled
    }" :disabled="disabled || loading" :autofocus="autofocus" :type="nativeType">
        <Icon :icon="icon" v-if="icon"></Icon>
        <Icon icon="spinner" spin v-if="loading"></Icon>
        <span>
            <slot></slot>
        </span>
    </button>
</template>

可以通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的属性:详情见Vue3官方文档 defineExpose,我们可以使用组件暴露的属性,当你需要的时候:

js 复制代码
<script>
import type { ButtonInstance } from './components/Button/types'
const buttonRef = ref<ButtonInstance | null>(null)

const testRef = () => {
 if (buttonRef.value) {
    console.log('buttonRef', buttonRef.value.ref)
  } 
} 
</script>

<template>
  <Button ref="buttonRef" @click="testRef">Test Button</Button>
</template>

如图:

关于组件样式

组件样式比较多,本组件库大部分样式借鉴于Element Plus,这里不再一一赘述,详见 Element Plus官方

关于其他属性

Button还有更多的属性,这里只是实现一个简易版的组件,只实现常用的样式和属性,本组件库的目的也是实现常用组件的常用属性

总结

通过上述文章,实现了Button组件的基本样式和常用属性。

我们不难发现,传递属性通过Vue3父子组件之间常用的通信方式------props,之后的组件还将用到子传父emits,以及隔代组件通信provideinject

还有Vue3编译宏相关的APIdefineExpose,它允许我们显式地指定哪些变量或函数应该被暴露给组件外部。这在当我们希望父组件能够访问子组件内部的某些状态或方法时非常有用。

相关推荐
吕彬-前端6 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱9 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai18 分钟前
uniapp
前端·javascript·vue.js·uni-app
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205872 小时前
web端手机录音
前端
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb