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

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.rhkb.cn/news/327348.html

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

相关文章

C语言笔记15

指针2 1.数组名的理解 int arr[ 10 ] { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int *p &arr[ 0 ];17391692786 arr是数组名&#xff0c;数组名是首元素地址&#xff0c;&arr[0]就是取出首元素的地址放在指针变量p中。 #include <stdio.h> int main()…

【激活函数--中】激活函数和阶跃函数的可视化及对比

文章目录 一、Python中绘制阶跃函数的图形二、实现和可视化Sigmoid函数2.1 Python实现2.2 可视化Sigmoid函数 三、比较Sigmoid函数与阶跃函数3.1 Sigmoid函数与阶跃函数的差异3.2 Sigmoid函数与阶跃函数的共同点 一、Python中绘制阶跃函数的图形 在Python中实现阶跃函数的代码…

NodeJS编写后端接口

技术栈 1.express&#xff1a;Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建 各种 Web 应用&#xff0c;和丰富的 HTTP 工具&#xff0c;使用 Express 可以快速地搭建一个完整功能的网站。 2.mysql&#xff1a;用于操作MySQL数据库 3.bod…

高校普法|基于SSM+vue的高校普法系统的设计与实现(源码+数据库+文档)

高校普法系统 目录 基于SSM&#xff0b;vue的高校普法系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3律师功能模块 4学生功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获…

2024中国(厦门)国际医用消毒及感控设备展览会

2024中国&#xff08;厦门&#xff09;国际医用消毒及感控设备展览会 2024 China (Xiamen) International Medical Disinfection And Infection Control Exhibition 致力于打造医用消毒及感控设备产业采购一站式平台 时 间&#xff1a;2024年11月1-3日 November 1-3, 2024 …

揭秘奇葩环境问题:IDEA与Maven版本兼容性解析

1.问题描述 最近在实现通过Java爬虫获取网页源码&#xff0c;然后紧接着将源码转换为图片上传到OSS服务器&#xff0c;其中探索了很多办法&#xff0c;但是在实现过程中遇到一个奇葩问题&#xff0c;就是我无论下载任何Maven依赖&#xff0c;都无法正常下载&#xff0c;简直是…

零基础HTML教程(32)--HTML5语义化标签

文章目录 1. div时代2. div的缺点3. 语义化标签4. 语义化标签有哪些5. 实战演练6. 小结 1. div时代 我是2009年开始学习网页开发的&#xff0c;那时候HTML里面到处是div。 这么说吧&#xff0c;那时候div就是网页的骨架&#xff0c;支撑着网页的主结构。 2. div的缺点 div作…

vulhub靶机struts2环境下的s2-032(CVE-2016-3081)(远程命令执行漏洞)

影响范围 Struts 2.3.19至2.3.20.2、2.3.21至2.3.24.1和2.3.25至2.3.28 当用户提交表单数据并验证失败时&#xff0c;后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析&#xff0c;然后重新填充到对应的表单数据中。 漏洞搭建 没有特殊要求&#xff0c;请看 (3…

C#知识|上位机UI设计-详情窗体设计思路及流程(实例)

哈喽,你好啊,我是雷工! 上两节练习记录了登录窗体和主窗体的实现过程,本节继续练习内容窗体的实现,以下为练习笔记。 01 详情窗体效果展示: 02 添加窗体并设置属性 在之前练习项目的基础上添加一个Windows窗体,设置名称为:FrmIPManage.cs 设置窗体的边框和标题栏的外…

Vision Mamba 代码调试---Pycharm+AutoDL

《AutoDL使用手册》 1. 服务器租用与配置 先上项目链接&#xff1a; GitHub - hustvl/Vim: Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 1.1 服务器租用与配置 根据环境要求&#xff0c;去租一个服务器&#xff1a;AutoDL算…

基于FPGA的音视频监视器,音视频接口采集器的应用

① 支持1路HDMI1路SDI 输入 ② 支持1路HDMI输出 ③ 支持1080P高清屏显示实时画面以 及叠加的分析结果 ④ 支持同时查看波形图&#xff08;亮度/RGB&#xff09;、 直方图、矢量图 ⑤ 支持峰值对焦、斑马纹、伪彩色、 单色、安全框遮幅标记 ⑥ 支持任意缩放画面&#xff0c;支…

深入解析RedisJSON:在Redis中直接处理JSON数据

码到三十五 &#xff1a; 个人主页 JSON已经成为现代应用程序之间数据传输的通用格式。然而&#xff0c;传统的关系型数据库在处理JSON数据时可能会遇到性能瓶颈。为了解决这一问题&#xff0c;Redis推出了RedisJSON模块&#xff0c;它允许开发者在Redis数据库中直接存储、查询…

文心一言 VS 讯飞星火 VS chatgpt (259)-- 算法导论19.3 2题

二、使用聚合分析来证明 FIB-HEAP-DECREASE-KEY 的 O(1) 摊还时间是每一个操作的平均代价。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; FIB-HEAP-DECREASE-KEY 是斐波那契堆&#xff08;Fibonacci Heap&#xff09;操作中的一个&#xff0c;它允许我们减少堆…

Excel如何设置密码保护【图文详情】

文章目录 前言一、Excel如何设置密码保护&#xff1f;二、Excel如何取消密码保护&#xff1f;总结 前言 在软件项目开发过程中&#xff0c;会输出很多技术文档&#xff0c;其中也包括保密级别很高的服务器账号Excel文档。为了确保服务器账号相关的Excel文档的安全性&#xff0…

1-1ARM开发环境搭建(GD32)

1:安装MDK最好是5.27以及以上版本&#xff0c;避免后续学习中出现相关错误 2&#xff1a;安装芯片支持包 双击安装即可&#xff0c;也可以是默认路径&#xff0c;也可以自己更改路径 3&#xff1a;安装jlink下载器驱动&#xff08;下载调试器&#xff09; 具体安装步骤如下所示…

汇昌联信科技:拼多多电商的运营流程有哪些?

在当今互联网高速发展的时代&#xff0c;电商平台层出不穷&#xff0c;其中拼多多以其独特的团购模式和低价策略迅速崛起&#xff0c;成为众多消费者和商家的新宠。那么&#xff0c;拼多多电商的运营流程究竟包含哪些环节呢?接下来&#xff0c;我们将从商品上架、营销推广、订…

ctfshow web入门 php反序列化 web267--web270

web267 查看源代码发现这三个页面 然后发现登录页面直接admin/admin登录成功 然后看到了 ///backdoor/shell unserialize(base64_decode($_GET[code]))EXP <?php namespace yii\rest{class IndexAction{public $checkAccess;public $id;public function __construct(){…

一篇详解Git版本控制工具

华子目录 版本控制集中化版本控制分布式版本控制 Git简史Git工作机制Git和代码托管中心局域网互联网 Git安装基础配置git的--local&#xff0c;--global&#xff0c;--system的区别 创建仓库方式1git init方式2git clone git网址 工作区&#xff0c;暂存区&#xff0c;本地仓库…

k8s v1.20二进制部署 部署 CNI 网络组件 部署 Calico

一、部署 flannel 1.1.K8S 中 Pod 网络通信 ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容器是不会跨宿主机的&#xff09;共享同一个网络命名空间&#xff0c;相当于它们在同一台机器上一样&#xff0c;可以用 localhost 地址访问彼此的端口。…