背景
由于项目需要,我们需要开发一个可视化的vue组件库,目前拟通过 StoryBook + Vue的方式实现。
项目地址: github地址
技术选型
- docz : 虽然说支持Vue,但是我看是通过 Vuera 包的方式进行套壳操作,这样和dumi基本无差,放弃。
- dumi: 支持react。
- StoryBook:可交互,支持Vue,react。
综上所述。选StoryBook。
框架推荐
搭载Vue@3.0,使用vite。
实现
- vite初始化项目(storybook必须在已有项目中使用)
vite create my-vue-app
yarn install
- vite项目创建完毕,创建 storybook
npx storybook@latest init
完毕,你的package.json会变为
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
同时src会多一个文件夹:stories
-
配置storybook的主题等信息,可以参考官网:
https://storybook.js.org/ -
配置完毕,在
components中写组件
,在stories
中引用 components 中的组件 生成对应的主题库。 -
其中组件封装:
<template>
<button type="button" :class="classes" @click="onClick" :style="style">{{ label }} </button>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
const props = withDefaults(defineProps<{
/**
* The label of the button
*/
label: string,
/**
* primary or secondary button
*/
primary?: boolean,
/**
* size of the button
*/
size?: 'small' | 'medium' | 'large',
/**
* background color of the button
*/
backgroundColor?: string,
}>(), { primary: false });
const emit = defineEmits<{
(e: 'click', id: number): void;
}>();
const classes = computed(() => ({
'storybook-button': true,
'storybook-button--primary': props.primary,
'storybook-button--secondary': !props.primary,
[`storybook-button--${props.size || 'medium'}`]: true,
}));
const style = computed(() => ({
backgroundColor: props.backgroundColor
}));
const onClick = () => {
emit("click", 1)
};
</script>
<style scoped>
.storybook-button {
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
border: 0;
border-radius: 3em;
cursor: pointer;
display: inline-block;
line-height: 1;
}
.storybook-button--primary {
color: white;
background-color: #1ea7fd;
}
.storybook-button--secondary {
color: #333;
background-color: transparent;
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
}
.storybook-button--small {
font-size: 12px;
padding: 10px 16px;
}
.storybook-button--medium {
font-size: 14px;
padding: 11px 20px;
}
.storybook-button--large {
font-size: 16px;
padding: 12px 24px;
}
</style>
components下新建index.ts
import Button from "./button/index.vue";
// 按需引入
export { Button };
const component = [Button];
const IscasUI = {
// @ts-ignore
install(App) {
component.forEach((item) => {
App.component(item.name, item);
});
},
};
export default IscasUI;
vite.config.ts配置
import { defineConfig } from 'vite'
import vue from "@vitejs/plugin-vue";
import path from "path";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
outDir: "iscas-ui", //输出文件名称
lib: {
entry: path.resolve(__dirname, "./src/components/index.ts"), //指定组件编译入口文件
name: "iscas-ui",
fileName: "iscas-ui",
}, //库编译模式配置
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ["vue"],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: "Vue",
},
},
}, // rollup打包配置
},
})
打包:npm run build
在生成的iscas-ui
文件夹,npm 初始化,配置对应package.json
npm init
terminal登录npm,发布:npm publish
storybook发布:
yarn build-storybook
使用
- 下载npm包
npm i iscas-ui
- vue中使用
main.js 配置
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import "../node_modules/iscas-ui/style.css"; //引入组件样式
import IscasUI from "iscas-ui"; //导入
createApp(App).use(IscasUI).mount('#app')
App.vue使用
<script setup></script>
<template>
<IscasButton size="large" type="primary">我是测试组件ss</IscasButton>
</template>
<style scoped></style>