Vue组件库开发(1)按钮

131 阅读3分钟

在搭建Vue博客的时候,我们会需要很多封装好的组件,因此可以顺手写一个组件库,完成自己的需要。

创建项目

由于是Vue组件,因此肯定是基于Vue环境搭建的Vue+Vite,并且因为组件库比起一般的业务来说需要更严谨一些,因此我们使用typescript进行编写、使用cypress进行单元测试。

创建项目后,除了Vue和Vite之外,又添加了一些typescript和cypress的配置文件,不必惊慌,等到需要使用的时候我们便会对其进行讲解。

创建一个组件

我们首先创建一个button.vue,并按以下方式组织文件目录:

easy-components
├─ .git
│  ├─ // ...
├─ .gitignore
├─ env.d.ts
├─ index.html
├─ package-lock.json
├─ package.json
├─ packages
│  ├─ button // 按钮组件
│  │  ├─ index.ts // 注册组件
│  │  └─ src
│  │     └─ button.vue // 组件的.vue文件
│  └─ index.ts // 注册组件库
├─ public
│  └─ favicon.ico
├─ README.md
├─ src
│  ├─ App.vue
│  └─ main.ts
├─ tsconfig.config.json
├─ tsconfig.json
└─ vite.config.ts

对应的`button.vue`文件如下:

```html
<script lang="ts" setup>

</script>

<template>
    <div class = 'ec-button'>
        <slot></slot>
    </div>
</template>

<style scoped>

.ec-button{
    border: 10px;
    border-color: black;
    border-radius: 5%;
    height: 5vh;
    width: 10vw;
}

.ec-button:hover{
    animation-duration: 0.5s;
    animation-name: pointerAt;
    animation-iteration-count: 1;
    animation-fill-mode: forwards;
    cursor: pointer;
}

@keyframes pointerAt{
    from{

    }
    to{
        background-color: #FFD103;
    }
}

</style>

组件注册

如果是一个一般的Vue项目,那么此时在其他文件中,我们就可以使用这个新创建的组件了。但是由于我们这是组件库,因此需要在其他地方动一动手脚。

为了能够让typescript文件引入vue组件,我们需要关闭vscode内置的typescript插件(在插件栏中搜索@buildin typescript),并使用Volar插件进行接管。

接下来就可以在button/index.ts文件中对组件进行引入了。

import ecButton from "./src/button.vue"
import type { App } from 'vue';
// 仅类型导入

ecButton.install= (app: App):void =>{
    app.component("ecButton", ecButton);
}

export default ecButton;

之后便可以为整个组件库的index.ts文件注册了。

import type { App } from 'vue'
import ecButton from './button'

// 所有组件列表
const components = [ ecButton ]

// 定义 install 方法, App 作为参数
const install = (app: App): void => {
    components.forEach(component => {
        app.use(component as unknown as { install: () => any })
    })
}

export {
    ecButton,
}

export default {
    install
}

基本测试与使用

目前我们就相当于写好了一个组件库。那么如何使用它呢?首先我们需要修改已经存在的项目配置,让其适应组件库这种项目。首先是给/packages路径创建一个便捷的引用,其次是让import语句支持.ts文件。因此要对tsconfig.json进行修改。

{
  "extends": "@vue/tsconfig/tsconfig.web.json",
  "include": [
    "examples/**/*.ts",
    "examples/**/*.tsx",
    "examples/**/*.vue",
    "packages/**/*.ts",
    "packages/**/*.tsx",
    "packages/**/*.vue",
    "typings/**/*.ts",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "~/*": ["packages/*"]
    }
  },

  "references": [
    {
      "path": "./tsconfig.config.json"
    }
  ]
}

组件库是一个npm包,因此我们也要对packages.json进行修改,使其符合一个组件库的使用方法。

{
  "name": "easy-components",
  "version": "0.0.0",
  "private": false,
  "main": "lib/index.min.js",
  "module": "lib/index.esm.js",
  "typings": "lib/index.d.ts",
  "license": "MIT",
  "scripts": {
    "dev": "vite",
    "build": "run-p type-check build-only",
    "preview": "vite preview",
    "build-only": "vite build",
    "type-check": "vue-tsc --noEmit"
  },
  "dependencies": {
    "vue": "^3.2.47"
  },
  "devDependencies": {
    "@types/node": "^18.14.0",
    "@vitejs/plugin-vue": "^4.0.0",
    "@vue/tsconfig": "^0.1.3",
    "npm-run-all": "^4.1.5",
    "typescript": "~4.7.4",
    "vite": "^4.1.3",
    "vue-tsc": "^1.1.5"
  }
}

修改完毕后,就可以在App.vue中进行测试了。首先要在main.ts中进行引用。

import { createApp } from 'vue'
import App from './App.vue'
import easyComponents from '~/index'

const app =createApp(App);
app.use(easyComponents);
app.mount('#app')

接下来在App.vue中进行对应的测试编写。

<script setup lang="ts">

</script>

<template>
  <ecButton>
    111
  </ecButton>
</template>

经过测试是发现可以顺利使用的。

为组件添加属性

目前我们只有一个按钮,也没有任何的属性可以提供。现在我们需要对按钮加以改进。我们要添加一个isActive属性,该属性是一个Boolean值,决定按钮是否可用。

使用typescript为vue组件定义props可以有三种方法,一种是使用object传入,另一种是使用泛型方法,还有一种是使用接口定义传入。在这里我们使用最后一种方法。

interface Props{
    isActive?: boolean
}

const props = defineProps<Props>()

但是目前我们需要一个默认值。在使用这种方法定义的时候,我们就不能直接通过改变接口的方式对默认值定义,需要使用withDefaults方法。

interface Props{
    isActive?: boolean
}

const props = withDefaults(defineProps<Props>(),{
    isActive: true,
})

同时使用v-class,对css进行修改。

<script lang="ts" setup>
interface Props{
    isActive?: boolean
}

const props = withDefaults(defineProps<Props>(),{
    isActive: true,
})
</script>

<template>
    <div class = 'ec-button' :class="{active: props.isActive}">
        <slot></slot>
    </div>
</template>

<style scoped>

.ec-button{
    /*边框*/
    border: 1px;
    border-color: black;
    border-style: solid;
    border-radius: 2em;
    /*大小*/
    height: 5vh;
    width: 10vw;
    /*文本位置*/
    text-align: center;  
}

.ec-button:hover{
    cursor: not-allowed;
}

.active:hover{
    animation-duration: 0.5s;
    animation-name: pointerAt;
    animation-iteration-count: 1;
    animation-fill-mode: forwards;
    cursor: pointer;
}

@keyframes pointerAt{
    from{
    }
    to{
        background-color: #FFD103;
    }
}

</style>

注意,如果传参的时候想传入false,请一定要使用v-bind,因为false是一个JavaScript表达式,而不是一个字符串。

至此一个基本的组件就写好了。在接下来的过程中,我们会开发更多的组件,用来对Vue博客进行更好的协助开发。