npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@qxs-bns/components

v0.0.88

Published

Vue 3 Component Library

Readme

@qxs-bns/components

QXS Business System 组件库,基于 Vue 3 + TypeScript + Element Plus 构建的企业级组件库。

✨ 特性

  • 🎯 企业级 - 专为企业级应用设计,提供丰富的业务组件
  • 🔧 二次封装 - 基于 Element Plus 进行增强,保持 API 一致性
  • 📦 按需加载 - 支持 Tree-shaking,减少打包体积
  • 🎨 主题定制 - 支持主题定制和暗黑模式
  • 🌍 国际化 - 内置国际化支持
  • 📱 响应式 - 移动端友好的响应式设计
  • 无障碍 - 遵循 WAI-ARIA 标准
  • 🎪 TypeScript - 完整的 TypeScript 类型定义

📦 安装

# npm
npm install @qxs-bns/components

# yarn
yarn add @qxs-bns/components

# pnpm
pnpm add @qxs-bns/components

🚀 快速开始

完整引入

import { createApp } from 'vue'
import QxsComponents from '@qxs-bns/components'
import '@qxs-bns/components/dist/index.css'
import App from './App.vue'

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

按需引入

<template>
  <QxsButton type="primary">按钮</QxsButton>
  <QxsDataChart :data="chartData" show-type-name="bar" />
</template>

<script setup>
import { QxsButton, QxsDataChart } from '@qxs-bns/components'

const chartData = {
  data: [
    { name: '一月', value: 100 },
    { name: '二月', value: 200 }
  ]
}
</script>

🏗️ 项目结构

packages/components/
├── src/                    # 源码目录
│   ├── button/            # 按钮组件
│   │   ├── src/           # 组件源码
│   │   │   └── button.vue
│   │   ├── style/         # 组件样式
│   │   │   └── index.scss
│   │   └── index.ts       # 组件入口
│   ├── data-chart/        # 数据图表组件
│   ├── utils/             # 工具函数
│   ├── constants/         # 常量定义
│   └── index.ts           # 总入口
├── dist/                  # 构建产物
├── docs/                  # 组件文档
└── package.json

🧩 核心组件

基础组件

| 组件名 | 说明 | 文档 | |--------|------|------| | Button | 按钮组件 | 查看文档 | | Input | 输入框组件 | 查看文档 | | Select | 选择器组件 | 查看文档 |

数据展示

| 组件名 | 说明 | 文档 | |--------|------|------| | DataChart | 数据图表组件 | 查看文档 | | Table | 表格组件 | 查看文档 | | Card | 卡片组件 | 查看文档 |

导航组件

| 组件名 | 说明 | 文档 | |--------|------|------| | Menu | 菜单组件 | 查看文档 | | Breadcrumb | 面包屑组件 | 查看文档 | | Pagination | 分页组件 | 查看文档 |

反馈组件

| 组件名 | 说明 | 文档 | |--------|------|------| | Dialog | 对话框组件 | 查看文档 | | Message | 消息提示组件 | 查看文档 | | Loading | 加载组件 | 查看文档 |

🛠️ 开发指南

环境要求

  • Node.js >= 16
  • pnpm >= 7
  • Vue >= 3.3
  • TypeScript >= 4.9

本地开发

# 克隆项目
git clone <repository-url>

# 安装依赖
pnpm install

# 启动开发服务器
pnpm dev

# 构建组件库
pnpm build

# 运行测试
pnpm test

创建新组件

  1. 创建组件目录

    mkdir src/my-component
    cd src/my-component
  2. 创建必要文件

    my-component/
    ├── src/
    │   └── my-component.vue
    ├── style/
    │   └── index.scss
    ├── index.ts
    └── README.md
  3. 组件模板

    <!-- src/my-component.vue -->
    <template>
      <div :class="ns.b()">
        <slot />
      </div>
    </template>
    
    <script setup lang="ts">
    import { useNamespace } from '@qxs-bns/hooks'
    
    defineOptions({
      name: 'QxsMyComponent'
    })
    
    const ns = useNamespace('my-component')
    </script>
  4. 样式文件

    // style/index.scss
    @use 'sass:map';
    @use '@qxs-bns/theme-chalk/src/mixins/mixins' as *;
    @use '@qxs-bns/theme-chalk/src/common/var' as *;
    
    @include b(my-component) {
      // 组件样式
    }
  5. 入口文件

    // index.ts
    import { withInstall } from '@qxs-bns/utils'
    import MyComponent from './src/my-component.vue'
    
    export const QxsMyComponent = withInstall(MyComponent)
    export default QxsMyComponent
    
    export * from './src/my-component'

📋 开发规范

组件命名规范

Element Plus 二次封装组件

  • 组件名:保持与 Element Plus 一致,添加 Qxs 前缀
  • 文件名:使用 kebab-case
  • 样式类名:使用 Element Plus 的 BEM 命名规范
// ✅ 正确示例
export const QxsButton = withInstall(Button)
export const QxsInput = withInstall(Input)

// ❌ 错误示例
export const QxsBtn = withInstall(Button)
export const QxsInputField = withInstall(Input)

自定义组件

  • 组件名:使用 @qxs-bns/hooks 中的 useNamespace 函数
  • 文件名:使用 kebab-case
  • 样式类名:使用 BEM 命名规范
<script setup lang="ts">
import { useNamespace } from '@qxs-bns/hooks'

defineOptions({
  name: 'QxsDataChart' // 组件名使用 PascalCase
})

const ns = useNamespace('data-chart') // 使用 kebab-case
</script>

<template>
  <div :class="ns.b()"> <!-- 生成 .qxs-data-chart -->
    <div :class="ns.e('header')"> <!-- 生成 .qxs-data-chart__header -->
      <div :class="ns.em('header', 'title')"> <!-- 生成 .qxs-data-chart__header--title -->

Props 设计规范

// 使用 TypeScript 接口定义 Props
interface ButtonProps {
  /**
   * 按钮类型
   * @default 'default'
   */
  type?: 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'default'

  /**
   * 按钮尺寸
   * @default 'default'
   */
  size?: 'large' | 'default' | 'small'

  /**
   * 是否禁用
   * @default false
   */
  disabled?: boolean

  /**
   * 是否加载中
   * @default false
   */
  loading?: boolean
}

// 使用 withDefaults 设置默认值
const props = withDefaults(defineProps<ButtonProps>(), {
  type: 'default',
  size: 'default',
  disabled: false,
  loading: false
})

事件设计规范

// 定义事件类型
interface ButtonEmits {
  /**
   * 点击事件
   * @param event 原生事件对象
   */
  click: [event: MouseEvent]

  /**
   * 焦点事件
   * @param event 原生事件对象
   */
  focus: [event: FocusEvent]

  /**
   * 失焦事件
   * @param event 原生事件对象
   */
  blur: [event: FocusEvent]
}

const emit = defineEmits<ButtonEmits>()

// 事件处理
const handleClick = (event: MouseEvent) => {
  if (props.disabled || props.loading) return
  emit('click', event)
}

样式规范

SCSS 变量使用

// 使用主题变量
@use '@qxs-bns/theme-chalk/src/common/var' as *;

@include b(button) {
  // 使用 CSS 变量
  background-color: var(#{getCssVarName('button', 'bg-color')});
  border-color: var(#{getCssVarName('button', 'border-color')});
  color: var(#{getCssVarName('button', 'text-color')});

  // 状态样式
  @include when(disabled) {
    opacity: var(#{getCssVarName('disabled-opacity')});
    cursor: not-allowed;
  }

  // 修饰符样式
  @include m(primary) {
    background-color: var(#{getCssVarName('color-primary')});
    border-color: var(#{getCssVarName('color-primary')});
  }
}

BEM 命名规范

// Block(块)
.qxs-button { }

// Element(元素)
.qxs-button__icon { }
.qxs-button__text { }

// Modifier(修饰符)
.qxs-button--primary { }
.qxs-button--large { }

// State(状态)
.qxs-button.is-disabled { }
.qxs-button.is-loading { }

🧪 测试规范

单元测试

// button.test.ts
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import Button from '../src/button.vue'

describe('Button', () => {
  it('should render correctly', () => {
    const wrapper = mount(Button, {
      props: { type: 'primary' },
      slots: { default: 'Click me' }
    })

    expect(wrapper.classes()).toContain('qxs-button--primary')
    expect(wrapper.text()).toBe('Click me')
  })

  it('should emit click event', async () => {
    const wrapper = mount(Button)
    await wrapper.trigger('click')

    expect(wrapper.emitted('click')).toHaveLength(1)
  })

  it('should not emit click when disabled', async () => {
    const wrapper = mount(Button, {
      props: { disabled: true }
    })
    await wrapper.trigger('click')

    expect(wrapper.emitted('click')).toBeUndefined()
  })
})

组件快照测试

// button.snap.test.ts
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import Button from '../src/button.vue'

describe('Button Snapshots', () => {
  it('should match snapshot with different types', () => {
    const types = ['primary', 'success', 'warning', 'danger', 'info']

    types.forEach(type => {
      const wrapper = mount(Button, {
        props: { type },
        slots: { default: 'Button' }
      })
      expect(wrapper.html()).toMatchSnapshot(`button-${type}`)
    })
  })
})

📖 文档规范

组件文档模板

每个组件都应该包含完整的 README.md 文档:

# Button 按钮

常用的操作按钮。

## 基础用法

基础的按钮用法。

:::demo 使用 `type`、`plain`、`round` 和 `circle` 属性来定义 Button 的样式。

button/basic

:::

## API

### Button Attributes

| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
|--------|------|------|--------|--------|
| type | 类型 | string | primary / success / warning / danger / info / text | — |
| size | 尺寸 | string | large / small / mini | — |
| disabled | 是否禁用状态 | boolean | — | false |

### Button Events

| 事件名 | 说明 | 参数 |
|--------|------|------|
| click | 点击时触发 | (event: Event) |

### Button Slots

| 插槽名 | 说明 |
|--------|------|
| — | 默认插槽 |

🤝 贡献指南

提交规范

使用 Conventional Commits 规范:

# 新功能
feat(button): add loading state support

# 修复 bug
fix(data-chart): resolve chart rendering issue

# 文档更新
docs(readme): update installation guide

# 样式调整
style(button): adjust padding and margin

# 重构代码
refactor(utils): optimize namespace function

# 性能优化
perf(table): improve virtual scrolling performance

# 测试相关
test(button): add unit tests for disabled state

开发流程

  1. Fork 项目
  2. 创建功能分支
    git checkout -b feat/new-component
  3. 开发组件
    • 编写组件代码
    • 添加单元测试
    • 编写文档
  4. 提交代码
    git add .
    git commit -m "feat(new-component): add new component"
  5. 推送分支
    git push origin feat/new-component
  6. 创建 Pull Request

代码审查清单

  • [ ] 组件命名符合规范
  • [ ] TypeScript 类型定义完整
  • [ ] 单元测试覆盖率 > 80%
  • [ ] 文档完整且示例可运行
  • [ ] 样式符合设计规范
  • [ ] 无障碍性支持
  • [ ] 国际化支持

🔧 常见问题

Q: 如何自定义主题?

A: 通过 CSS 变量覆盖默认主题:

:root {
  --qxs-color-primary: #409eff;
  --qxs-color-success: #67c23a;
  --qxs-color-warning: #e6a23c;
  --qxs-color-danger: #f56c6c;
  --qxs-color-info: #909399;
}

Q: 如何按需引入组件?

A: 使用 ES6 模块语法:

import { QxsButton, QxsInput } from '@qxs-bns/components'

Q: 如何贡献新组件?

A: 请参考 贡献指南 部分。

📄 许可证

MIT License - 详见 LICENSE 文件。