Vue3组件库开发项目实战——03封装Button组件/输出vitePress文档

news2024/11/20 8:47:33

Vue3组件库开发项目实战——01组件开发必备知识导学-CSDN博客

Vue3组件库开发项目实战——02项目搭建(配置Eslint/Prettier/Sass/Tailwind CSS/VitePress/Vitest)-CSDN博客

在前面两篇博客中,我分别介绍了组件库开发必学知识,以及项目所需的所有依赖的引入和安装。在本文将带你动手开发Button组件,并输出vitepress文档中。本文的目标是输出下面的vitePress示例

开发组件使用的是JSX语法,即在js中描述dom的创建,然后使用前面介绍的将vue用在模板中的指令通过js的语法转译。你可能觉得很难看懂,但是不着急,每段代码我都有详细注释。不要轻易放弃,坚持住,不难的。慢慢来吧

 欢迎关注我的git关于这部分的源码

https://github.com/OneDayInMarch/ui-component

点击右上角的Starred ,点击code进行下载

 回顾JSX语法

当在 Vue 3 中结合使用 JSX 时,可以利用 JSX 的灵活性和直观性来创建 Vue 组件。以下是一些在 JSX 中结合 Vue 3 的语法特点:

使用 defineComponent 定义组件: 在 JSX 中,可以使用 defineComponent 函数来定义 Vue 组件,通过 setup 函数来设置组件的逻辑。

import { defineComponent } from 'vue';

const MyComponent = defineComponent({
  setup() {
    return () => (
      <div>Hello, Vue 3 JSX!</div>
    );
  },
});

export default MyComponent;

模板语法: 在 JSX 中,可以直接在组件中使用 Vue 的模板语法,比如插值、指令等。

return () => (
  <div>
    <h1>{msg}</h1>
    <button v-on:click={handleClick}>Click me</button>
  </div>
);

动态属性和事件处理: 可以通过大括号 {} 来动态绑定属性和事件处理函数。

const isDisabled = ref(false);

return () => (
  <button disabled={isDisabled.value} onClick={handleClick}>Click me</button>
);

条件渲染和列表渲染: 可以使用 JSX 的语法来进行条件渲染和列表渲染。

return () => (
  <div>
    {showMessage && <p>{message}</p>}
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  </div>
);

组件嵌套: 可以在 JSX 中嵌套其他组件,实现组件的复用和组合。

const ParentComponent = defineComponent({
  setup() {
    return () => (
      <div>
        <ChildComponent />
      </div>
    );
  },
});

通过结合使用 JSX 和 Vue 3,可以更加灵活地创建复杂的交互式界面,同时充分利用 Vue 3 的响应式系统和组件化能力。

Button初始化

在src/components中新建一个button文件夹。button文件夹下新增src文件夹和index.ts

src里新增button.tsx文件。indext.ts用于将button按钮导出

初始化button.tsx

这部分我截图,你可以跟着敲,不要养成复制代码的习惯。后面会给出较为完整的代码,中间过程就省略了代码复制了。

初始化index.ts

main.ts挂载Button组件

 利用helloword组件测试Button

 可以看到<u-button>按钮被编译为button按钮。并且“确定”替换了UButton组件的默认值“按钮”。Button按钮初具雏形

 封装按钮类型

常见的比如element-ui和ant-design-vue的按钮是不是都提供了丰富的类型选择。link、text、primary等。参考优秀的组件库,我们也设置按钮的类型。

新增button-type.ts文件;添加如下代码

导出buttonProps和ButtonProps

  1. ButtonProps 是一个类型定义,用于指定组件 UButton 的 props 的类型。在 setup 函数中,通过 props: ButtonProps 来指定 props 的类型为 ButtonProps,从而在代码中使用类型检查和智能提示。

  2. buttonProps 则是一个对象,用于定义 UButton 组件的具体 props。通常情况下,buttonProps 包含了组件的各个 props 的定义,例如 typesizedisabled 等。这样做的好处是可以将 props 的定义集中在一个地方,便于维护和管理。

封装按钮样式

使用tailwind css的语法,通过在模板中使用简单的语法简化样式的实现。同时使用sass的var定义变量的方式定义样式变量,这样做的目的是可以在js运行时能够操作变量的方式实现网页动态换肤。

在CSS文件写tailwind css需要使用@apply显示的声明。否则编译器不认识是tailwind css的语法

1.抽离全局主题样式

新增style文件夹,及style/variable.scss文件

// 定义主题变量
$u-border-radius: var(--u-border-radius, 2px); //一般圆角
$u-font-size-md: var(--u-font-size-md, 12px); //当组件size为''时使用此字号大小
$u-animation-duration-slow: var(--u-animation-duration-slow, 300ms);
$u-animation-ease-in-out-smooth: var(
  --u-animation-ease-in-out-smooth,
  cubic-bezier(0.645, 0.045, 0.355, 1)
);
$u-light-text: var(--u-light-text, #ffffff); // 有色深色背景下字体颜色(固定)
$u-primary: var(--u-primary, #5e7ce0); // 主要按钮,同品牌色
$u-primary-hover: var(--u-primary-hover, #7693f5); // 主要按钮悬停
$u-primary-active: var(--u-primary-active, #344899); // 主要按钮激活
$u-text: var(--u-text, #252b3a); // 正文文本
$u-block: var(
  --u-block,
  #ffffff
); // 大面积的不可折叠区块的背景色(例如顶部导航背景色)
$u-line: var(--u-line, #adb0b8); // 边框分割线,仅用于边框
$u-form-control-line-active: var(
  --u-form-control-line-active,
  #5e7ce0
); // 表单控件边框激活色,用于获得焦点
$u-brand-active: var(--u-brand-active, #526ecc); // 品牌色激活色(加深)
$u-brand-active-focus: var(
  --u-brand-active-focus,
  #344899
); // 品牌色焦点色(重度加深)

样式以u-开头,表示我们当前自己写的组件的class名规范,以u-开头

以 $u-border-radius: var(--u-border-radius, 2px); 为例解析sass语法

  • $u-border-radius:这是一个变量名,以 $ 符号开头,用于存储一个值,这里是 border-radius 的值。
  • var(--u-border-radius, 2px);:这是CSS自定义属性(也称为CSS变量)的用法。var() 函数用于插入自定义属性的值。
    • --u-border-radius:这是一个自定义属性名,以 -- 开头,定义了一个名为 u-border-radius 的CSS变量。
    • 2px:这是自定义属性的默认值。如果 --u-border-radius 没有在当前作用域中定义或者未被设置,那么 var(--u-border-radius, 2px) 将使用这个默认值 2px

目前我们还没定义 --u-border-radius 这个变量,所以使用的是第二个参数默认值

2.button组件样式

新增如下样式目录结构

button-base.scss

通过mixin混入全局定义的变量样式。定义button-base代码块,用于后面设置u-btn{};替换括号里的内容。使用@apply是tailwind css在css中的语法格式。定义了一个button-variant函数,用于后面替换基础类和伪类使用的;这是因为基础类通过两层就能找到样式,而伪类比如hover需要三次才能找到background-color

@import '../../../style/variable.scss';

// 按钮基础样式
@mixin button-base {
  // 布局样式
  @apply inline-flex items-center justify-center;

  // 元素属性
  @apply border-[1px] border-solid border-transparent 
    h-[28px] py-0 px-[20px] bg-transparent;
  border-radius: $u-border-radius;

  // 文本属性
  @apply outline-0 leading-normal 
    whitespace-nowrap cursor-pointer;

  // 文字样式
  font-size: $u-font-size-md;

  // 其他样式
  transition:
    background-color $u-animation-duration-slow $u-animation-ease-in-out-smooth,
    border-color $u-animation-duration-slow $u-animation-ease-in-out-smooth,
    color $u-animation-duration-slow $u-animation-ease-in-out-smooth;
}
@mixin button-variant($variant, $pseudo: false) {
  @each $key, $value in $variant {
    // 第一层是多态的类型
    &.u-btn--#{$key} {
      @each $item-key, $item-value in $value {
        // 第二层是多态类型下的样式
        @if $pseudo {
          // 如果是伪类就继续第三层
          &:#{$item-key} {
            @each $sub-item-key, $sub-item-value in $item-value {
              // 第三层是伪类的样式
              #{$sub-item-key}: $sub-item-value;
            }
          }
        } @else {
          // 不是伪类就直接设置样式
          #{$item-key}: $item-value;
        }
      }
    }
  }
}

button-config.scss

@import '../../../style/variable';

// 按钮类型的配置
$type: (
  primary: (
    color: $u-light-text,
    background-color: $u-primary
  ),
  secondary: (
    color: $u-text,
    background-color: $u-block,
    border-color: $u-line
  ),
  text: (
    padding: 0,
    color: $u-brand-active
  )
);

// 伪类的配置
$pseudo: (
  primary: (
    hover: (
      background-color: $u-primary-hover
    ),
    focus: (
      background-color: $u-primary-hover
    ),
    active: (
      background-color: $u-primary-active
    )
  ),
  secondary: (
    hover: (
      border-color: $u-form-control-line-active,
      color: $u-brand-active
    ),
    focus: (
      border-color: $u-form-control-line-active,
      color: $u-brand-active
    ),
    active: (
      border-color: $u-form-control-line-active,
      color: $u-brand-active
    )
  ),
  text: (
    hover: (
      color: $u-brand-active-focus
    ),
    focus: (
      color: $u-brand-active-focus
    ),
    active: (
      color: $u-brand-active-focus
    )
  )
);

button.scss

通过import导入的代码最终会替换.u-btn{}括号里的具体值,对于多个类,比如u-btn--secondary也是在u-btn里面渲染出来的。这点可以通过渲染后的html页面看出来

// button/src/button.scss
@use './button-config';
@import './button-base';

.u-btn {
  // 导入button基础样式
  @include button-base;

  // 导入type相关的样式
  @include button-variant(button-config.$type);

  // 导入hover等伪类样式
  @include button-variant(button-config.$pseudo, true);
}

 $type就是区分类型,u-btn--secondary就是通过button-variant转换后得到的。$pseudo就是区分是否有伪类。

基础样式配置后,进入button基础组件开发。前面我们已经演示过一个默认type=secondary的按钮怎么在页面使用的。但是接下来我不准备继续在helloword组件中测试,而是使用vitepress写不同的button按钮。这样你就能更直观的看到封装的按钮及效果。

 vitepress引入Button组件

首先依次执行vitepress命令

三个命令都执行一遍,为了生成dist和cach目录

// 启动
npm run docs:dev

// 打包
npm run docs:build

// 预览
npm run docs:preview

添加gitignore

由于我们是项目中添加 vitepress 文档,所以还需要在 .gitignore 文件中,将 vitepress 缓存文件过滤一下。
docs/.vitepress/cache
docs/.vitepress/dist

在docs目录下新增vite.config.js

vitepress无法解析JSX格式文件,需要在vitepress里单独解决JSX问题。和UI-component整个文件的解决方式一样

在.vitepress目录下新增theme目录

添加index.ts

目的是引入主题和注册Button组件

跟着手写添加下面的代码(不要偷懒)

 docs下新增components文件夹

新增button\index.md文件

添加如下代码

 添加vitepress路由

在docs/.vitepress/config.mts文件中添加button的路由。跟前端路由一样,只不过是link的写法

 生成在线文档

还是利用我们在package.json文档中配置的docs:dev命令启动vitepress开发环境

 打开控制台给的端口,可以看到页面已经渲染出来了

 按button的type扩展button示例

扩展components\button\index.md

到目前为止一个基础的button组件就完成并显示出来了。对于业务来说,button组件远不止样式的不同,还有尺寸、禁用状态等。比如如下的button按钮样式。因此,接来下将扩展button的组件

 扩展Button功能——增加size类型

 修改button-type.ts

新增size属性、IButtonSize类型

 修改button.tsx

增加根据size渲染的类型

 修改style/variable.scss

增加字体需要的样式

button-config.scss  

修改src/components/button/style/button-config.scss

新增size变量

 修改button.scss

将定义的size变量引入

补充vitepress的button内容

docs/components/button/index.md

渲染效果

 扩展Button功能——增加disabled属性

进一步扩展button组件,增加disabled属性,表示button被禁用

 主要更改button-type增加类型;button.tsx增加属性;增加disable的渲染;丰富vitepress在线文档

 

  修改button-type.ts

 修改style/variable.scss  

 修改button.tsx

修改button.scss

 修改vitepress的button

渲染效果

 增加块级Button

块级按钮独占一行,宽度100%撑开父元素

有前面给按钮添加type、size、disable属性可知,封装button其实就是封装不同的样式。这里还是通过传递属性控制按钮是否为块级按钮。

 修改button-type.ts

增加block类型,布尔类型

修改button.tsx

在button.tsx中根据block的值给button按钮增加u-button--block样式

 修改button.scss

增加u-btn--block样式

 修改vitepress的button文档

渲染效果

总结

对于Button的封装是很简单的,核心就是button.tsx文件——创建一个可定制样式的按钮组件 UButton,根据传入的 props 动态渲染按钮的样式和行为。

比较复杂的就是样式的定义,对于一个Button组件,我们写了很多css的样式,定义变量、全局的、局部的变量。

其实组件库开发就是干这几件事:

写样式、定义父子通信、插槽

然后组件库开发还涉及到组件的结构设计、文档编写、测试等方面。综合考虑这些方面,可以开发出功能完善、易用且易维护的组件库。

接下来,我将介绍如何在组件开发中使用vitest进行组件单元测试:vitest登场——对button组件进行单元测试。关注我,带你同步学习组件化开发~

源码获取

 欢迎关注我的git关于这部分的源码

https://github.com/OneDayInMarch/ui-component

点击右上角的Starred ,点击code进行下载

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

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

相关文章

整合Tess4J图文识别技术

仓库地址&#xff1a;https://gitee.com/z3inc/tess4j-demo.git 1. OCR图文识别介绍 OCR&#xff08;全称 Optical Character Recognition&#xff0c;直译为光学字符识别&#xff09;用于图片文字识别&#xff0c;例如 提取图片中车牌号等等。 Java中实现OCR的技术方案有&…

文本到语音的学习笔记:从Docker开始

1.docker 是什么意思&#xff1f; Docker 是一种开源的容器化平台&#xff0c;它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中&#xff0c;然后可以在任何支持Docker的系统上运行这个应用&#xff0c;而不必担心环境差异导致的问题。 以下是Docker的一些关键特…

品鉴中的精神内涵:如何通过红酒品味生活的美好与哲学

红酒不仅仅是一种物质享受&#xff0c;更是一种精神体验。在品鉴云仓酒庄雷盛红酒的过程中&#xff0c;我们能够品味到生活的美好与哲学&#xff0c;感受到红酒所蕴含的精神内涵。 红酒的精神内涵源于其酿造过程中所融入的时间和匠心。一瓶上好的红酒需要经过长时间的陈年&…

二叉树专题(有关二叉树的相关学习)

二叉树 1.数概念及结构 1.1树的结构 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个特殊的结…

使用yarn/npm安装插件(涉及electron),总是报错证书错误或者ssl解析错误

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、问题描述二、解决措施总结 前言 最近electron更新到了30大版本&#xff0c;里面更新的一个重大变化是主进程增加了 WebContentsView 和 BaseWindow&#xff0c;对窗口的控制会更加丝滑。 正好最近在做把文章或者视频…

网页转长图插件html2canvas【前端】

网页转长图插件html2canvas【前端】 前言版权开源推荐网页转长图插件html2canvas【前端】wkImageStorage流程使用后端application.propertiesWkConfigShareControllerImageCleanupTask 前端html2canvas.jsshare.htmlshare.jsgetShare.jsgetShare.html 最后 前言 2024-5-10 18:…

linux学习:多媒体开发库SDL+视频、音频、事件子系统+处理yuv视频源

目录 编译和移植 视频子系统 视频子系统产生图像的步骤 api 初始化 SDL 的相关子系统 使用指定的宽、高和色深来创建一个视窗 surface 使用 fmt 指定的格式创建一个像素点​编辑 将 dst 上的矩形 dstrect 填充为单色 color​编辑 将 src 快速叠加到 dst 上​编辑 更新…

SpringAMQP Work Queue 工作队列

消息模型: 代码模拟: 相较于之前的基础队列&#xff0c;该队列新增了消费者 不再是一个&#xff0c;所以我们通过代码模拟出两个consumer消费者。在原来的消费者类里写两个方法 其中消费者1效率高 消费者2效率低 RabbitListener(queues "simple.queue")public voi…

经典文献阅读之--U-BEV(基于高度感知的鸟瞰图分割和神经地图的重定位)

0. 简介 高效的重定位对于GPS信号不佳或基于传感器的定位失败的智能车辆至关重要。最近&#xff0c;Bird’s-Eye-View (BEV) 分割的进展使得能够准确地估计局部场景的外观&#xff0c;从而有利于车辆的重定位。然而&#xff0c;BEV方法的一个缺点是利用几何约束需要大量的计算…

React useEffect Hook: 理解和解决组件双重渲染问题

在React中&#xff0c;useEffect可能会在组件的每次渲染后运行&#xff0c;这取决于它的依赖项。如果你发现useEffect运行了两次&#xff0c;并且你正在使用React 18或更高版本的严格模式&#xff08;Strict Mode&#xff09;&#xff0c;这可能是因为在开发模式下&#xff0c;…

解锁楼宇自动化新维度西门子Insight+BACnet IP I/O控制器

数字城市的楼宇自动化已不再是一个遥不可及的概念&#xff0c;而是成为了现代建筑的标配。特别是在大型商业综合体、高端写字楼和公共设施中&#xff0c;高效的楼宇管理系统是确保环境舒适度与能源效率的关键。当提及楼宇自动化领域的佼佼者&#xff0c;西门子Insight楼宇自动化…

Spring WebFlux:响应式编程

在软件开发领域&#xff0c;随着互联网应用的规模和复杂性不断增加&#xff0c;传统的编程模型逐渐暴露出一些局限性&#xff0c;尤其是在面对高并发、大规模数据流处理等场景时。为了应对这些挑战&#xff0c;响应式编程&#xff08;Reactive Programming&#xff09;应运而生…

AuroraFOC使用指南一(STM32F405双路FOC)

一. 简介 哈喽&#xff0c;感谢各位选择AuroraFOC开发板&#xff0c;在这里将对其进行一个详细的介绍&#xff0c;方便大家使用。并且对提供的工程文件和上位机的操作也进行了详细的说明。 有什么疑问或者好的建议 可以微信联系: WU1356742146 最后再次感谢大家的支持。 Aur…

Transformers中加载预训练模型的过程剖析(一)

使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记…

PostgreSQL 用户及授权管理 04:授予及回收权限

PostgreSQL 是一个坚如磐石的数据库&#xff0c;它非常注重安全性&#xff0c;提供了非常丰富的基础设施来处理权限、特权和安全策略。在前面的章节中以我们介绍的基本概念为基础&#xff0c;重新审视角色概念&#xff0c;特别关注授予角色的安全性和权限&#xff08;角色可以是…

Linux/ubuntu build编译make时出现has modification time int the future的问题解决方法

针对Linux由于双系统之间的时间冲突导致linux时间经常变化&#xff0c;出现执行make命令时出现“make[2]: Warning: File xxx.c’ has modification time 1.6e05 s in the future “警告的问题&#xff0c;亦或者虚拟机出现相同的问题。 由于时钟同步问题&#xff0c;出现 warn…

CAST: Cross-Attention in Space and Time for Video Action Recognition

标题&#xff1a;CAST: 时空交叉注意力网络用于视频动作识别 原文链接&#xff1a;2311.18825v1 (arxiv.org)https://arxiv.org/pdf/2311.18825v1 源码链接&#xff1a;GitHub - KHU-VLL/CASThttps://github.com/KHU-VLL/CAST 发表&#xff1a;NeurIPS-2023&#xff08;CCF A…

SwiftUI 调整视图内容周围间隙(Content Margins)的“时髦”方法

概述 在 SwiftUI 开发的应用中,往往在小屏设备(比如 iPhone)上布局良好的 App 放到大屏(iPad)上后就会“一塌糊涂”。因为它们一味的只想着“占据”却不知道“舍弃”。 从 iOS 17.0(iPad 17.0)开始苹果提供了原生的视图修改器方法专注于处理此事。 在本篇博文中,您将…

MVC WebAPI

创建项目 创建api控制器 》》》 web api 控制器要继承 ApiController 》》》 数据会自动装配 及自动绑定 》》》》FromBody&#xff1a; Post请求的基础类型的参数和Get请求有点不一样&#xff0c;我们知道Get请求的参数是通过Url来传递的&#xff0c;而Post请求则是通过H…

华为涅槃,余承东重生

最近一段时间&#xff0c;余承东甚为低调。最为明显的是&#xff0c;“遥遥领先”已经听不到了&#xff0c;“余大嘴”口中的措辞越来越克制。 今后手机相关的发布会&#xff0c;或许不再看到余承东的身影。 5月10日&#xff0c;余承东的职位正式更新&#xff0c;从终端BG CE…