# vue3组件库项目学习笔记(二):开发一个组件

news2024/12/23 8:13:25

在搭建了基础架构之后,我们就需要编写一个完整的组件,它应该包括数据接口,样式,组件的 vue 文件等等内容

编写组件

我们知道,组件都有很多的属性字段,并且部分的属性是可以枚举的,所以我们将这些会传递进组件的内容都写下来,放在 types.ts 文件中

import type { ExtractPropTypes } from 'vue';
//枚举可以枚举字段的内容
export const ButtonType = ['primary', 'text'];

export const ButtonSize = ['large', 'small'];

export const buttonProps = {
  //判定内容在枚举字段内
  type: {
    type: String,
    validator(value: string) {
      return ButtonType.includes(value);
    }
  },
  size: {
    type: String,
    validator(value: string) {
      return ButtonSize.includes(value);
    }
  },
  //圆角
  round: Boolean,
  //禁用
  disabled: Boolean
};
//导出
export type ButtonProps = ExtractPropTypes<typeof buttonProps>;

之后我们来编写我们组件的核心逻辑,我们的写法如下,我们首先接收一个传入组件的参数集合,然后根据这些参数来改变我们组件的样式,到达配置我们组件的目的,最后使用 slot 插槽来将按钮内部的内容输入其中:

<script lang="ts" setup>
import "./style/index.less";
import { computed } from "vue";
import { buttonProps } from "./types";
const props = defineProps(buttonProps);
console.log(props)

const styleClass = computed(() => {
  return {
    "ls-button":true,
    [`ls-button-${props.type}`]: props.type,
    "is-round": props.round,
    "is-disabled": props.disabled,
    [`ls-button-${props.size}`]: props.size,
  };
});
</script>
<template>
  <button  :class="styleClass">
    <slot />
  </button>
</template>

在完成了逻辑之后,我们为其编写对应的样式,放在 style/index.less 文件中,你可以按照自己的喜好来编写自己喜欢的样式:

.ls-button {
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #dcdfe6;
  color: #606266;
  appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  margin: 0;
  transition: 0.1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;

  &:hover {
    color: #409eff;
    border-color: #c6e2ff;
    background-color: #ecf5ff;
  }
}

.ls-button-primary {
  color: #fff;
  background-color: #409eff;
  border-color: #409eff;

  &:hover {
    background: #66b1ff;
    border-color: #66b1ff;
    color: #fff;
  }
}

.ls-button-text {
  border-color: transparent;
  color: #409eff;
  background: transparent;
  padding-left: 0;
  padding-right: 0;

  &:hover {
    color: #66b1ff;
    border-color: transparent;
    background-color: transparent;
  }
}

.ls-button.is-disabled {
  color: #c0c4cc;
  cursor: not-allowed;
  background-image: none;
  background-color: #fff;
  border-color: #ebeef5;
}

.ls-button-primary.is-disabled,
.ls-button-primary.is-disabled:active,
.ls-button-primary.is-disabled:focus,
.ls-button-primary.is-disabled:hover {
  color: #fff;
  background-color: #a0cfff;
  border-color: #a0cfff;
}

.ls-button-primary.is-disabled.is-plain,
.ls-button-primary.is-disabled.is-plain:active,
.ls-button-primary.is-disabled.is-plain:focus,
.ls-button-primary.is-disabled.is-plain:hover {
  color: #8cc5ff;
  background-color: #ecf5ff;
  border-color: #d9ecff;
}

.ls-button-large {
  padding: 10px 20px;
  font-size: 14px;
  border-radius: 4px;
}

.ls-button-small {
  padding: 9px 15px;
  font-size: 12px;
  border-radius: 3px;
}

.is-round {
  border-radius: 20px;
}

使用 app.use

我们希望我们的组件可以使用 app.use 方法来挂载,所以我们需要提供一个方法,在我们的 utils 的index.ts 内把内容改写成这个方法

import type { Plugin } from "vue"

export const withInstall = <T, E extends Record<string, any>>(main: T, extra?: E): T => {
  (main as SFCWithInstall<T>).install = (app): void => {
    for (const comp of [main, ...Object.values(extra ?? {})]) {
      app.component(comp.name, comp);
    }
  };

  if (extra) {
    for (const [key, comp] of Object.entries(extra)) {
      (main as any)[key] = comp;
    }
  }
  return main as SFCWithInstall<T> & E;
};

export type SFCWithInstall<T> = T & Plugin;

然后我们可以在 button 组件的 index.ts 内调用这个方法来提供组件这个能力

import { withInstall } from '@ls-ui/utils'
import Button from './button.vue'
const LsButton = withInstall(Button)
export default LsButton

最后我们在 components 文件夹下 与 package.json 同级的位置创建一个 index.ts 文件,提供一个 install 方法,因为 app.use 要求我们传入的参数具有这个方法

import components from './src/index'
export * from './src/index'
import { App } from 'vue'
import { version } from './package.json';

const install = function (app: App): void {
  Object.entries(components).forEach(([key, value]) => {
    app.component(key, value);
  });
};

export default {
  install,
  version
};

别忘了修改我们的 package.json 文件,让他的 main 模块指向我们的刚刚写好的文件

"main": "index.ts",

一切完成之后,我们就可以在 examples 里调用我们的模块了 ,在 main.ts 文件里使用 app.use 的方法来调用

import { createApp } from 'vue';
import App from './app.vue';
import LsButton from "ls-ui"

const app = createApp(App);
app.use(LsButton as any)
app.mount('#app')

之后在 app.vue 文件里尝试调用它,如果不出以外,你的界面上将会现实一个蓝色的按钮,并且它具有圆角

<template>
  <div>
    <ls-button type="primary" size="small" round >
      哈哈哈哈哈
    </ls-button>
  </div>
</template>
<script lang="ts" setup>
</script>

组件Attrs与方法

我们继续完善我们的组件,比如我们希望我们的组件具有 name 属性,就想原生的 html 元素一样,我们可以定义一个props 然后再来写我们的 props属性,再绑定到组件代码上,但是其实对于这种情况,我们可以使用 Attrs 来实现。通过它可以获得绑定在组件上,但是 prosp 内不接收的属性,如果原生的 html 元素和我们的组件上都需需要某个元素并且作用相同,我们可以利用它简化我们的代码

通过 useAttrs 方法我们可以获得我们需要的内容,再通过 v-bind 绑定到我们的按钮上:

<script lang="ts" setup>
import { useAttrs  } from "vue";
//...
const attrs = useAttrs()
console.log(attrs)
//.....
</script>
<template>
  <button  :class="styleClass"  v-bind="attrs" >
    <slot />
  </button>
</template>

之后我们在我们的组件里传递一个 name 属,此时打开F12 定位到我们的button,可以看到我们的标签上具有 name = "lst" 这个字段:

<ls-button type="primary" size="small" round name="lst">
     哈哈哈哈哈
</ls-button>

然后我们可以理所当然的想到,一个按钮最重要的就是具有作用,比如我们点击它的时候产生一些效果,所以我们应该为我们的组件添加一个可以相应的方法,其实也很简单,和 vue 父子组件通信是一样的,以下的完整的demo:

<script lang="ts" setup>
import "./style/index.less";
import { computed , useAttrs , defineEmits } from "vue";
import { buttonProps } from "./types";
const props = defineProps(buttonProps);
console.log(props)
const attrs = useAttrs()
console.log(attrs)


const emits = defineEmits(['click'])

const styleClass = computed(() => {
  return {
    "ls-button":true,
    [`ls-button-${props.type}`]: props.type,
    "is-round": props.round,
    "is-disabled": props.disabled,
    [`ls-button-${props.size}`]: props.size,
  };
});

const myClick = ( ) => {
  emits('click', 11);
}
</script>
<template>
  <button  :class="styleClass"  v-bind="attrs" @click="myClick()">
    <slot />
  </button>
</template>

app.vue

<template>
  <div>
    <ls-button type="primary" size="small" round name="lst" @click="test">
      哈哈哈哈哈
    </ls-button>
  </div>
</template>
<script lang="ts" setup>
const test = ( msg:number ) => {
  console.log(msg);
};
</script>

然后在你点击按钮之后在控制台打印出 2 那么你的组件就编写完成了

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

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

相关文章

Vmware Pro 17 设置共享文件夹

目录 一、概述 二、在VMware设置共享文件夹详细步骤 一、概述 VMware 是运行在Windows系统上的&#xff0c;很多时候需要将 Windows 系统上的资料或代码复制到运行在VMware上的虚拟机&#xff0c;通常有两种方法可以完成复制&#xff0c;一个是在Vmware软件上设置共享文件夹&…

网络分层模型和应用协议

网络分层模型和应用协议 分层模型 分层模型的意义 当遇到一个复杂问题的时候&#xff0c;可以使用分层的思想把问题简单化。 比如&#xff0c; 你有一杯82年的可乐&#xff0c;想要分享给你的朋友张富贵&#xff0c;但你们已经很久没有联系&#xff0c;要完成这件事&#xf…

《深入浅出计算机组成原理》学习笔记 Day2

文章目录指令篇1. 从高级语言到机器指令1.1 CPU的作用1.2 代码如何变为机器码1.3 指令的分类2. 指令跳转2.1 CPU 是如何执行指令2.2 条件和循环的本质3. 函数调用3.1 栈的作用3.2 Stack Overflow指令篇 1. 从高级语言到机器指令 计算机或者说CPU本身并没有能力去理解这些高级…

配置远程服务器时候sftp的配置以及注意事项【在本地配置sftp】

我之所以不用PutTy是因为这个工具有问题&#xff0c;在我的电脑上怎么也安装不上&#xff0c;也找了很多办法根本没用。如这个 我试过修改权限以及各种安装办法连安装都不行。 所以才决定直接使用vscode自带的上传工具上传到服务器。 想要上传到服务器&#xff0c;需要使用vsc…

2023牛客寒假算法基础集训营1 -- G-鸡格线(map + 内置二分写法)

题目如下&#xff1a; 示例1 输入 3 5 0 2 114514 2 1 1 2 2 2 1 1 3 1 2输出 114516 114551 3445思路 or 题解&#xff1a; 通过 f(x)round(10∗x)f(x) round(10*\sqrt{x})f(x)round(10∗x​) 我们可得到&#xff1a; 经过至多 111111 次 0 -> 01~99 -> 99100 ~ i…

如何利用jar命令把前端代码打进jar包

目录背景介绍简单介绍几个常用的jar命令参数查询一个文件在jar包中的位置将文件解压到当前目录把一个目录打包进jar把一个文件打包进jar更新jar的shell脚本update.sh命令执行过程部分截图背景介绍 前后端分离是目前主流的开发模式&#xff0c;部署的时候也是利用类似nginx实现…

C++之多态

文章目录一、多态的理解二、多态的定义及实现1.多态的构成条件2.虚函数3.虚函数的重写/覆盖4. C11 的 override 和 final5.重载、重写/覆盖、隐藏/重定义三、抽象类四、多态的原理1.虚函数表2.多态的原理3.动态绑定与静态绑定五、单继承和多继承关系的虚函数表1.单继承中的虚函…

【Git】IDEA 集成 Git

7、IDEA 集成 Git 7.1、配置 Git 忽略文件 1、Eclipse 特定文件 2、IDEA 特定文件 3、Maven 工程的 target 目录 问题 1:为什么要忽略他们&#xff1f; 答&#xff1a;与项目的实际功能无关&#xff0c;不参与服务器上部署运行。把它们忽略掉能够屏蔽 IDE 工具之间的差异。 …

联合变换相关器摄远物镜光学设计

联合变换相关器摄远物镜光学设计 联合变换相关器工作原理 随着科学技术的飞速发展&#xff0c;光学相关探测器件由最初的匹配滤波器发展到今天的联合变换相关器&#xff0c;联合变换相关器与范得耳-卢格特相关器相比&#xff0c;具有灵活性好、识别精度高等特点&#xff0c;所…

Media基础知识一

1.视频文件是什么&#xff1f; FLV, MKV, MP4是不同的视频后缀名&#xff0c;不同的视频格式就像一个容器。容器里封装的是音视频流。 FFmpeg&#xff1a;一款开源软件&#xff0c;用来处理音视频&#xff0c;对音视频进行编解码。要在Android中使用FFmpeg&#xff0c;需要下载…

vue-element-admin 换肤功能,登录后不同权限不同皮肤,刷新不会失效

一、拉vue-element-admin的代码跑起来 安装依赖时会遇到一些问题&#xff0c;tui-editor装不上&#xff0c;需要按照以下步骤删除它 1、vue-element-admin\package.json 删除‘tui-editor’&#xff1a;‘1.3.3’依赖项。 2、vue-element-admin\src\components 删除MarkdownE…

C++ 三种智能指针及其设计实现unique_ptr、 share_ptr 指针

0、差不多春节啦。。。。。 好久没有写博客&#xff0c;写一写吧。。。。。。 祝大家嗨皮&#xff0c;提前恭喜发财 1、三种智能指针的使用方法 C 有3种指针&#xff1a;share_ptr, unique_ptr, weak_ptr 1.1&#xff09;unique_ptr 指针 std::unique_ptr 是一种独占的智能指…

Sklearn标准化和归一化方法汇总(1):标准化 / 标准差归一化 / Z-Score归一化

Sklearn中与特征缩放有关的五个函数和类&#xff0c;全部位于sklearn.preprocessing包内。作为一个系列文章&#xff0c;我们将逐一讲解Sklearn中提供的标准化和归一化方法&#xff0c;以下是本系列已发布的文章列表&#xff1a; Sklearn标准化和归一化方法汇总(1)&#xff1a…

ESP32 (WIFI)-AP、STA模式(13)

提示&#xff1a;本博客作为学习笔记&#xff0c;有错误的地方希望指正 文章目录一、ESP32 WIFI模式概述二、ESP32 WIFI-AP初始化流程三、WIFI-AP示例四、ESP32 WIFI-STA初始化流程五、WIFI-STA示例一、ESP32 WIFI模式概述 参考资料&#xff1a;ESP IDF编程手册V4.4   WIFI主…

【GD32F427开发板试用】Systick系统定时器的使用

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;HonestQiao 基于Arm Cortex-M系列内核的MCU&#xff0c;都包含了SysTick定时器。 所谓SysTick即为系统定时器&#xff0c;又称嘀嗒定时器&am…

Docker Swarm

Swarm 是什么&#xff1f; Docker Swarm 是Docker官方的跨节点的容器编排工具。用户只需要在单一的管理节点上操作&#xff0c;即可管理集群下的所有节点和容器。 主要解决什么问题 1. 解决docker server的集群化管理和部署。 2. Swarm通过对Docker宿主机上添加的标签信息来…

分享60个PHP源码,总有一款适合您

PHP源码 分享60个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 60个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/1SvjbzolwuMrQyhVb_byG5Q?pwdx831 提取码&#xff…

生物素点击标记试剂:DBCO-SS-PEG3-biotin,1430408-09-5,生物素PEG3二硫键DBCO

1、理论分析&#xff1a;中文名&#xff1a;生物素-三聚乙二醇-二硫-二苯并环辛炔&#xff0c;生物素-PEG3-二硫-DBCO &#xff0c;生物素PEG3-二硫二苯并环辛炔英文名&#xff1a;DBCO-S-S-PEG3-biotin&#xff0c;Biotin-PEG3-SS-DBCOCAS号&#xff1a;1430408-09-5化学式&am…

如何使用ArcGIS进行点抽稀

01 概述对于制图工作者而言&#xff0c;遇到大量的点要素&#xff08;POI、村名等&#xff09;标注的时候往往非常的麻烦&#xff0c;因为这些点往往都是十分的密集&#xff0c;直接标注很影响制图的美观。如果直接去处理原始的数据&#xff0c;会导致后续的数据更新维护麻烦&a…

pdf合并在线,大家都在用的工具

工作和生活当中都有很多场景需要我们提交PDF文档&#xff0c;而且有时候要求仅能提交一份&#xff0c;如果这时候刚好你的文档分成了几份&#xff0c;就得先合并之后才能提交。要在线合并PDF并不麻烦&#xff0c;关键是用对工具。下面就来给大家介绍几款热门的软件&#xff0c;…