在搭建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博客进行更好的协助开发。