Skip to content

Latest commit

 

History

History
282 lines (217 loc) · 8.13 KB

File metadata and controls

282 lines (217 loc) · 8.13 KB

Bunny-UI 优化建议


一、Bug 修复

1. src/js/bunny.js 第 67 行 — 孤立代码

  escapeChars: function (str) {
      if (typeof str !== 'string') {
-         q
          str = String(str);
      }

q 是遗留的无效语句,应删除。

2. src/js/alert.js — transformResponse 缺少非 JSON 返回

  transformResponse: function (text, xhr, elt) {
      if (xhr.getResponseHeader('Content-Type')
          .includes('application/json')) {
          const data = JSON.parse(xhr.responseText)
          bny.alert(data.msg, data.code || 0, data.anim || 'scale', data.time || 3)
          return elt.innerHTML
      }
+     return text
  }

当响应非 JSON 时,没有 return text,会导致返回 undefined

3. src/js/bunny.jsremoveClass 逻辑缺陷

  removeClass: function (elt, cls) {
      if (!elt) console.error('removeClass: 元素不存在')
-     if (typeof elt === 'object') {
+     if (typeof elt === 'object' && !Array.isArray(elt) && !(elt instanceof NodeList)) {
          Object.keys(elt).forEach((key) => {
              elt[key].classList.remove(cls)
          })
+         return
      }
      if (Array.isArray(elt) || elt instanceof NodeList) {
          Array.from(elt).forEach(e => e.classList.remove(cls))
          return
      }

typeof elt === 'object' 会同时匹配普通对象和 NodeList,导致 NodeList 走不到正确分支。


二、架构改进

1. 添加组件销毁机制

当前所有组件只有初始化逻辑,没有清理逻辑。应利用 htmx:beforeCleanupNode 钩子:

// 示例:dropdown 清理
onEvent: function (name, evt) {
    if (name === 'htmx:beforeCleanupNode') {
        if (bny.hasExtName(evt.target, 'bny-dropdown')) {
            const dropdown = bny.queryChild(evt.target, '.bny-dropdown')
            if (dropdown) dropdown.remove()
            // 移除 document 上绑定的 click 监听器
        }
    }
}

2. JSON 解析增加错误处理

所有 transformResponse 中的 JSON.parse 应加上 try-catch:

transformResponse: function (text, xhr, elt) {
    if (xhr.getResponseHeader('Content-Type').includes('application/json')) {
        try {
            const data = JSON.parse(xhr.responseText)
            // ...
        } catch (e) {
            console.error('[bny-menu] JSON 解析失败:', e)
            return text
        }
    }
    return text
}

3. 补充键盘无障碍支持

组件 需要支持的键盘操作
bny-menu ↑↓ 导航、Enter 激活、Escape 关闭、→ 展开子菜单
bny-dropdown Escape 关闭、Tab 焦点管理
bny-tab ←→ 切换标签、Delete 关闭(当 closable 时)
bny-nav Tab 导航、Enter 激活
bny-collapse Enter/Space 切换展开
bny-confirm Enter 确认、Escape 取消

4. 添加 TypeScript 类型定义

建议创建 types/bunny.d.ts,提供 API 智能提示:

declare namespace bny {
    function alert(msg: string, code?: number, anim?: string, time?: number): void
    function confirm(msg: string, options?: ConfirmOptions): void
    function page(content: string, options?: PageOptions): HTMLElement
    function load(style?: number, options?: LoadOptions): HTMLElement
    // ...
}

5. src/js/tab.js 拆分重构

当前 312 行过于臃肿,建议拆分为:

  • tab-core.js — 初始化、标签切换、去重逻辑
  • tab-scroll.js — 滚动按钮、左右滑动
  • tab-close.js — 关闭当前/其他/全部逻辑

三、CSS 改进

1. 硬编码颜色值替换为 CSS 变量

  &[color="green"] {
      border-color: var(--green);
-     background-color: rgba(5, 150, 105, 0.08);
+     background-color: var(--green-alpha-10);
      color: var(--green);
  }

base.css 中补充颜色半透明变量:

--green-alpha-10: rgba(5, 150, 105, 0.08);
--green-alpha-20: rgba(5, 150, 105, 0.15);
--blue-alpha-10: rgba(2, 132, 199, 0.08);
--yellow-alpha-10: rgba(217, 119, 6, 0.08);
--red-alpha-10: rgba(225, 29, 72, 0.08);

2. button.css 属性语义化

- &[model~="border"] {
+ &[variant="border"] {
      background-color: transparent;

model 改为 variant 更符合业界惯例。

3. grid.css offset 语义修正

- & .col-xs-offset1 { grid-column-end: 2; }
+ & .col-xs-offset1 { grid-column-start: 2; }

使用 grid-column-startgrid-column-end 更准确地表达"偏移"语义。

4. 颜色变体代码 DRY 化

大量组件中 green/yellow/red/blue 四色变体代码重复,可考虑使用 CSS 预处理器或 PostCSS 插件(如 postcss-each)生成:

/* 伪代码示例 */
@each $color in green, yellow, red, blue {
    &[color="$(color)"] {
        background-color: var(--$(color));
        border-color: var(--$(color));
    }
}

四、建议新增组件

高优先级

组件 说明 参考 API
Toast / Notification 非阻塞式消息通知,支持多位置、多类型 bny.toast('操作成功', { type: 'success' })
Pagination 分页组件,配合表格使用 <div hx-ext="bny-page">
Tooltip / Popover 气泡提示,12 方向自动定位 data-tooltip="提示内容"
Skeleton 骨架屏加载占位 <div class="bny-skeleton">

中优先级

组件 说明
Drawer 屏幕边缘滑出面板,可替代 page 做侧边栏表单
Upload 拖拽上传 + 点击上传,hx-post 驱动
Progress 百分比进度条,支持条纹动画
Breadcrumb 面包屑导航
Tree 树形控件,可复用 menu 部分逻辑
Carousel 轮播图

低优先级

组件 说明
Steps 步骤条,多步骤表单引导
Timeline 时间轴
Avatar / Badge 头像/徽标,纯 CSS 组件
Rate 星级评分
DatePicker 日期选择器,复杂度较高
Image Preview 图片预览,点击放大

五、优先级路线图

Phase 1(补基础)
├── Bug 修复(3 项)
├── JSON 解析错误处理
├── Toast / Notification
└── Pagination

Phase 2(提体验)
├── 组件销毁机制
├── 键盘无障碍支持
├── Skeleton
├── Tooltip / Popover
└── Drawer

Phase 3(扩场景)
├── CSS 硬编码颜色变量化
├── Upload
├── Progress
├── Breadcrumb
└── Tree

Phase 4(增丰富)
├── button.css 属性语义化
├── tab.js 拆分重构
├── TypeScript 类型定义
├── Carousel / Steps / Timeline
└── Rate / Avatar / Badge

六、补充说明

全局 API 扩展建议

当前 bny 全局对象已提供 alertconfirmpageload 四个顶层 API,建议新增:

window.bny = {
    // 现有 API
    alert: function (msg, code, anim, time) { ... },
    confirm: function (msg, options) { ... },
    page: function (content, options) { ... },
    load: function (style, options) { ... },

    // 建议新增
    toast: function (msg, options) { ... },    // 通知
    drawer: function (content, options) { ... }, // 抽屉
    modal: function (content, options) { ... },  // 模态框(增强版 confirm)
}

文档完善

  • 当前 test/ 目录下有丰富示例页面,但缺少组件 API 文档
  • 建议为每个组件编写 data-* 属性说明和 JavaScript API 说明
  • index.html 中的文档站可进一步结构化