四、组件调试
其实样式和组件是同步写的,但是写教程我就不排顺序了哈哈哈
我们这里就用 button 组件作为示例
1、基本结构
我们在 packages/components/ 下创建一个 button 目录
button.scss 写 button 组件的样式
button.ts 规范 button 组件的 prop
button.vue 组件主体
index.ts 对组件进行配置导出
2、button组件
我的实现代码如下
button.scss
@import '../../styles/common.scss';
.kl-button {
outline: none;
cursor: pointer;
border: $border-none;
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
min-width: var(--kl-size-width);
min-height: var(--kl-size-height);
font-size: var(--kl-size-font);
padding: 0 10px;
user-select: none;
background-color: var(--kl-bg-color);
color: var(--kl-font-color);
border: var(--kl-border);
& + & {
margin-left: 12px;
}
// transition
transition: all $transition-quick;
//circle
&.kl-circle {
border-radius: 50%;
padding: 15px;
min-width: 20px;
height: 20px;
}
//round
&.kl-round {
border-radius: 20px;
}
//disabled
&.kl-disabled {
cursor: not-allowed;
opacity: 0.6;
}
}
$defaultHoverBgColor: null;
@each $key, $value in $typeStyle {
@if $key == 'primary' {
$defaultHoverBgColor: map-get(
$map: $value,
$key: 'kl-bg'
);
}
}
//只有使用了type的才能正确使用plain
//遍历type找到当前匹配的类型
@each $key, $value in $typeStyle {
.kl-button--#{$key} {
@if $key == 'default' {
&:hover:not(.kl-disabled) {
--kl-border-color: #{rgba($color: $defaultHoverBgColor, $alpha: 0.5)};
--kl-border: var(--kl-border-width) var(--kl-border-style) var(--kl-border-color);
--kl-font-color: #{$defaultHoverBgColor};
--kl-bg-color: #{rgba($color: $defaultHoverBgColor, $alpha: 0.1)};
}
&:focus:not(.kl-disabled) {
--kl-border-color: #{rgba($color: $defaultHoverBgColor, $alpha: 0.5)};
--kl-border: var(--kl-border-width) var(--kl-border-style) var(--kl-border-color);
--kl-font-color: #{$defaultHoverBgColor};
--kl-bg-color: #{rgba($color: $defaultHoverBgColor, $alpha: 0.1)};
}
&:active:not(.kl-disabled) {
--kl-border-color: #{rgba($color: $defaultHoverBgColor, $alpha: 1)};
}
} @else {
&:hover:not(.kl-disabled) {
opacity: 0.6;
}
//激活样式
&:active:not(.kl-disabled) {
opacity: 1 !important;
@include kl-attribute($value, '--kl-bg-color', 'kl-bg-active');
}
}
&.kl-plain {
//如果是默认类型,不进行设置
@if $key == 'default' {
&:hover:not(.kl-disabled),
&:active:not(.kl-disabled) {
--kl-border-color: #{$defaultHoverBgColor};
--kl-font-color: #{$defaultHoverBgColor};
--kl-bg-color: #{$default-bgColor};
}
&:focus:not(.kl-disabled) {
--kl-border-color: #{$defaultHoverBgColor};
--kl-font-color: #{$defaultHoverBgColor};
--kl-bg-color: #{$default-bgColor};
}
} @else {
//给背景颜色设置透明度
--kl-bg-color: #{rgba($color: map-get($map: $value, $key: 'kl-bg'), $alpha: 0.1)};
//给字体设置当前type主题色
@include kl-attribute($value, '--kl-font-color', 'kl-bg');
//增加边框
--kl-border-color: #{map-get($map: $value, $key: 'kl-bg')};
--kl-border: var(--kl-border-width) var(--kl-border-style) var(--kl-border-color);
&:hover:not(.kl-disabled) {
opacity: 1 !important;
--kl-bg-color: #{rgba($color: map-get($map: $value, $key: 'kl-bg'), $alpha: 1)};
@include kl-attribute($value, '--kl-font-color', 'kl-fontColor');
}
&:focus:not(.kl-disabled) {
--kl-font-color: white;
--kl-bg-color: #{rgba($color: map-get($map: $value, $key: 'kl-bg'), $alpha: 1)};
}
&:active:not(.kl-disabled) {
opacity: 1 !important;
@include kl-attribute($value, '--kl-bg-color', 'kl-bg-active');
--kl-border-color: #{map-get($map: $value, $key: 'kl-bg-active')};
}
}
}
}
}
button.ts
import type { PropType } from 'vue'
export const typevalidator = (type: string): boolean => {
return ['primary', 'info', 'success', 'warning', 'danger'].includes(type)
}
// const sizeValidator = (size: string): boolean => {
// return ['normal', 'mini', 'small', 'large'].includes(size)
// }
export const ButtonProps = {
type: String as PropType<'primary' | 'info' | 'success' | 'warning' | 'danger'>,
size: String as PropType<'mini' | 'small' | 'normal' | 'large' | 'xlarge'>,
color: String,
textColor: {
type: String
},
round: Boolean,
plain: Boolean,
circle: Boolean,
disabled: Boolean
}
button.vue
<template>
<button
:class="[
n(),
type && n(`--${type}`),
size && n(`--${size}`),
round && 'kl-round',
plain && 'kl-plain',
circle && 'kl-circle',
disabled && 'kl-disabled'
]"
:style="{
...style
}"
>
<slot></slot>
</button>
</template>
<script setup lang="ts">
import { ButtonProps, typevalidator } from './button'
import { createNamespace } from '@kunlun-design/utils'
import { computed } from 'vue'
import './button.scss'
const props = defineProps(ButtonProps)
const style = computed(() => {
return props.color || props.textColor
? {
'--kl-bg-color': props.color,
'--kl-font-color': props.textColor,
'--kl-border-color': props.color,
'--kl-border': `var(--kl-border-width) var(--kl-border-style) var(--kl-border-color) var(--kl-border-style)`
}
: {}
})
//检测type是否符合规范
const type = computed(() => {
//首先验证的函数不允许是undefined 只允许string类型 如果类型非法就转换到默认类型
if (props.type === undefined) return 'default'
return typevalidator(props.type) ? props.type : 'default'
})
defineOptions({
name: 'KlButton'
})
const { n } = createNamespace('button')
</script>
<style scoped lang="scss"></style>
index.ts
export * from './src/button'
import { withInstall } from '@kunlun-design/utils'
import Button from './src/button.vue'
export const KlButton = withInstall(Button)
export default KlButton
components/index.ts
import './styles/common.scss'
export * from './button'
3、集中配置
我们需要有一个地方集中管理我们的组件
我们在 packages 目录下创建一个 kunlun-design 的目录
pnpm init
生成一个 package.json 文件,对他进行配置,以下是我的配置
{
"name": "kunlun-design",
"private": false,
"version": "0.0.16-alpha.03",
"author": "anixuil",
"description": "Kunlun Design - A Vue.js 3 UI library",
"keywords": [
"Kunlun-Design",
"Kunlun",
"kunlun-design",
"Kunlun Design",
"kunlun-design-vue"
],
"homepage": "https://github.com/1140040227/Kunlun-Design-Vue/tree/vitedev",
"repository": {
"type": "git",
"url": "https://github.com/1140040227/Kunlun-Design-Vue.git"
},
"files": [
"lib/*",
"packages/*",
"package.json"
],
"main": "./lib/kunlun-design-vue.umd.js",
"module": "./lib/kunlun-design-vue.mjs",
"exports": {
".": {
"import": "./lib/kunlun-design.mjs",
"require": "./lib/kunlun-design.umd.js"
},
"./lib/style.css": "./lib/style.css"
},
"engines": {
"node": ">=16.15.0"
}
}