青训营笔记-组件库开发(三)组件库的 helloworld (编写第一个组件)

73 阅读2分钟

四、组件调试

其实样式和组件是同步写的,但是写教程我就不排顺序了哈哈哈

我们这里就用 button 组件作为示例

1、基本结构

我们在 packages/components/ 下创建一个 button 目录

image-20230128172304241

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"
    }
}