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,它允许我们显式地指定哪些变量或函数应该被暴露给组件外部。这在当我们希望父组件能够访问子组件内部的某些状态或方法时非常有用。

相关推荐
一路向前的月光43 分钟前
react(9)-redux
前端·javascript·react.js
大数据追光猿1 小时前
Python中的Flask深入认知&搭建前端页面?
前端·css·python·前端框架·flask·html5
莫忘初心丶1 小时前
python flask 使用教程 快速搭建一个 Web 应用
前端·python·flask
xw52 小时前
Trae初体验
前端·trae
横冲直撞de2 小时前
前端接收后端19位数字参数,精度丢失的问题
前端
我是哈哈hh2 小时前
【JavaScript进阶】作用域&解构&箭头函数
开发语言·前端·javascript·html
摸鱼大侠想挣钱2 小时前
ActiveX控件
前端
谢尔登2 小时前
Vue 和 React 响应式的区别
前端·vue.js·react.js
后端小肥肠2 小时前
【AI编程】Java程序员如何用Cursor 3小时搞定CAS单点登录前端集成
前端·后端·cursor
酷酷的阿云2 小时前
Vue3性能优化必杀技:useDebounce+useThrottle+useLazyLoad深度剖析
前端·javascript·vue.js