# Snake UI 完整 LLM 上下文 此文件由 `pnpm skill:sync` 根据 `docs/` 自动生成,请不要直接编辑。 ## components # ButtonSort 排序按钮 用于在默认、升序和降序状态之间循环切换。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | 可选值 | | ------------ | -------------------------------- | -------- | ------ | ------ | | `title` | 按钮文字 | `string` | `''` | - | | `titleColor` | 按钮文字颜色,不传则用主题文字色 | `string` | `''` | - | ### Events | 事件名 | 触发时机 | 回调参数 | | -------- | -------------- | ---------------------------------- | | `change` | 排序状态切换后 | `{ value: '' \| 'asc' \| 'desc' }` | ## 主题变量 | 变量名 | 说明 | | -------------------------- | ------------------ | | `--snake-color-text` | 按钮文字默认颜色 | | `--snake-color-text-muted` | 未激活排序箭头颜色 | | `--snake-color-primary` | 激活排序箭头颜色 | # Button 按钮 基于 uni-app 原生 `button` 封装,覆盖常用属性、状态与交互。 ## 使用建议 用 Button 触发即时操作,例如提交表单、确认选择或调用平台开放能力。一个操作区只保留一个主要按钮;页面跳转优先使用 [Link](/components/link) 或明确的导航组件。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | 开放能力属性仅在对应平台生效。 ## 基础用法 ```vue 默认按钮 主要按钮 镂空按钮 小型胶囊按钮 加载中 不可操作 ``` ## 主题、尺寸和形状 `type` 支持 `default`、`primary`、`success`、`info`、`warning`、`error`。 `size` 支持 `large`、`default`、`medium`、`small`、`mini`;`shape` 支持 `square` 和 `circle`。 ```vue 主要按钮 警告按钮 中号按钮 胶囊按钮 ``` ## 水波纹与节流 ```vue 水波纹按钮 自定义水波纹 提交订单 ``` 开启 `ripple` 后不再叠加原生 `hover-class`。`disabled` 或 `loading` 时不会触发业务点击。 ## 异步提交 `throttle-time` 只限制连续点击;需要覆盖整个请求周期时,将 `loading` 绑定到提交状态。 ```vue 保存 ``` ```ts async function submit() { if (submitting.value) return; submitting.value = true; try { await saveData(); } finally { submitting.value = false; } } ``` ## 原生开放能力 ```vue 获取手机号 提交表单 ``` ## 无障碍 - 按钮文字应描述结果,例如“保存地址”,不要只写“确定”。 - 仅显示图标时,通过可见文字或平台支持的无障碍属性提供名称。 - 异步操作期间使用 `loading` 表达进度;除非确实不能再次提交,否则不要用永久禁用代替状态反馈。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | --------------- | ---------------------- | ------------------ | --------- | | `text` | 无默认插槽时显示的文本 | `string` | `''` | | `type` | 主题类型 | `string` | `default` | | `size` | 按钮尺寸 | `string` | `default` | | `shape` | 按钮形状 | `square \| circle` | `square` | | `plain` | 是否镂空 | `boolean` | `false` | | `hairLine` | 是否使用细边框 | `boolean` | `true` | | `disabled` | 是否禁用 | `boolean` | `false` | | `loading` | 是否显示原生加载状态 | `boolean` | `false` | | `ripple` | 是否开启水波纹 | `boolean` | `false` | | `rippleBgColor` | 水波纹颜色 | `string` | `''` | | `hoverClass` | 自定义按下类名 | `string` | `''` | | `throttleTime` | 点击节流时间,单位 ms | `number \| string` | `0` | | `customClass` | 根节点自定义类名 | `string` | `''` | | `customStyle` | 根节点自定义样式 | `string \| object` | `{}` | 其余原生能力参数包括 `scope`、`openType`、`formType`、`appParameter`、`hoverStopPropagation`、`lang`、`sessionFrom`、`sendMessageTitle`、`sendMessagePath`、`sendMessageImg`、`showMessageCard`、`dataName`、`hoverStartTime` 和 `hoverStayTime`。 ### Events 支持 `click`、`getuserinfo`、`contact`、`getphonenumber`、`error`、`launchapp`、`opensetting`、`chooseavatar` 和 `agreeprivacyauthorization`。 ### Slots | 名称 | 说明 | | --------- | ---------------------------------- | | `default` | 按钮内容;未提供时显示 `text` 属性 | ## 主题变量 Button 复用 Snake UI 全局颜色令牌,可在主题作用域内覆盖: | 变量 | 用途 | | ---------------------------- | ---------------- | | `--snake-color-primary` | 主要按钮颜色 | | `--snake-color-success` | 成功按钮颜色 | | `--snake-color-info` | 信息按钮颜色 | | `--snake-color-warning` | 警告按钮颜色 | | `--snake-color-error` | 错误按钮颜色 | | `--snake-color-white` | 实心按钮文字颜色 | | `--snake-color-text` | 默认按钮文字颜色 | | `--snake-color-border-light` | 默认按钮边框颜色 | | `--snake-color-surface` | 默认按钮背景颜色 | 各主题色还配有 `-dark`、`-disabled` 和 `-light` 状态令牌,完整定义见 `src/uni_modules/snake-ui/theme.scss`。 # Calendar 日历 用于单个日期或日期范围的选择,日历被包裹在底部弹起的容器中,支持农历、内置/自定义节日、节假日标记与打卡签到。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 范围与农历 ```vue ``` - `mode="date"` 单选:change 载荷为 `{ year, month, day, days, result, week, isToday, lunar }`。 - `mode="range"` 范围:change 载荷为 `{ startYear..., startDate, startWeek, endYear..., endDate, endWeek, startLunar, endLunar }`。 - `minDate`/`maxDate` 之外日期禁用;`defaultSelectToday` 初始化时默认选中今天(优先级低于 defaultDate/startDate/endDate)。 - `close` 在点击遮罩或关闭按钮收起时触发。 - `isPage` 为 true 时以页面内联方式展示,不使用弹窗,选择完成自动触发 change。 ## 自定义日期内容 设置 `use-date-slot` 后,可用 `date` 插槽渲染日期下方的补充信息。插槽参数 `date` 为当前日期信息,适合展示价格、库存或签到状态。 ```vue ``` `is-page` 适合嵌入预订、签到等页面;此模式不显示弹层标题和遮罩,外层不需要再维护打开/关闭状态。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------ | ----------------------------------------- | --------------------------- | ------------------------------------ | | `modelValue` | 双向绑定控制弹出与收起 | `boolean` | `false` | | `mode` | 选择模式 | `date \| range` | `date` | | `changeYear` / `changeMonth` | 是否显示年份/月份切换按钮 | `boolean` | `true` | | `maxYear` / `minYear` | 可切换的最大/最小年份 | `number \| string` | `2050` / `1950` | | `minDate` / `maxDate` | 最小/最大可选日期 | `number \| string` | `1950-01-01` / 今天 | | `defaultDate` | 默认选中的日期,mode 为 date 时生效 | `string` | `''` | | `startDate` / `endDate` | 默认开始/结束日期,mode 为 range 时生效 | `string` | `''` | | `defaultSelectToday` | 初始化时是否默认选中今天 | `boolean` | `true` | | `showLunar` | 是否显示农历 | `boolean` | `false` | | `showFestival` | 是否显示内置节日 | `boolean` | `false` | | `festivals` | 节日配置 `{ '04-04': '清明节' }` | `object` | `{}` | | `holidays` / `workdays` | 节假日/加班日列表 | `string[]` | `[]` | | `checkinMode` | 是否启用打卡签到模式 | `boolean` | `false` | | `checkedDates` | 已打卡日期列表 | `string[]` | `[]` | | `todayChecked` | 今日是否已打卡 | `boolean` | `false` | | `color` | 默认日期字体颜色 | `string` | `--snake-color-text` | | `activeBgColor` / `activeColor` | 选中日期背景/字体颜色 | `string` | `--snake-color-primary` / white | | `rangeBgColor` / `rangeColor` | 范围内日期背景/字体颜色 | `string` | 主题色浅色 / `--snake-color-primary` | | `monthArrowColor` / `yearArrowColor` | 月/年切换箭头颜色 | `string` | 文本次要色 / 文本弱化色 | | `startText` / `endText` | 起始/结束日期自定义文案 | `string` | 语言包默认值 | | `btnType` | 确定按钮样式类型 | `string` | `primary` | | `toolTip` | 顶部提示文字 | `string` | 语言包默认值 | | `closeable` | 是否显示右上角关闭图标 | `boolean` | `true` | | `isPage` | 是否在页面中直接显示,不使用弹窗 | `boolean` | `false` | | `readonly` | 是否只读,只读模式下禁止选择 | `boolean` | `false` | | `isChange` | 切换年月是否触发事件,mode 为 date 时生效 | `boolean` | `false` | | `isActiveCurrent` | 当前选中日期带选中效果 | `boolean` | `true` | | `borderRadius` | 弹窗顶部左右两边的圆角值 | `number \| string` | `20` | | `zIndex` | 弹出层级,0 使用弹层默认层级 | `number \| string` | `0` | | `maskCloseAble` | 是否允许点击遮罩关闭 | `boolean` | `true` | | `safeAreaInsetBottom` | 是否开启底部安全区适配 | `boolean` | `false` | | `useDateSlot` | 是否启用自定义日期内容插槽 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ------------------- | ---------------------------- | ----------------------- | | `update:modelValue` | 弹出/收起 | `boolean` | | `change` | 选择结果变化 | date/range 载荷(见上) | | `close` | 点击遮罩或关闭按钮收起 | - | | `input` | 弹窗通过按钮收起(兼容语义) | `false` | ### Slots | 名称 | 说明 | | --------- | ---------------------------- | | `tooltip` | 替换顶部提示文字 | | `date` | 自定义日期内容,携带日期信息 | ## 主题变量 | 变量 | 用途 | | ------------------------------ | -------------------------- | | `--snake-color-primary` | 选中日期、范围和工作日标记 | | `--snake-color-primary-rgb` | 日期范围浅色背景 | | `--snake-color-success` | 今日已打卡状态 | | `--snake-color-warning` | 已打卡日期状态 | | `--snake-color-error` | 节假日文字 | | `--snake-color-white` | 选中和打卡状态文字 | | `--snake-color-text` | 默认日期文字 | | `--snake-color-text-secondary` | 月份切换与辅助文字 | | `--snake-color-text-muted` | 年份切换与弱化文字 | | `--snake-color-text-light` | 未打卡日期状态 | | `--snake-color-border` | 不可选日期与边界 | | `--snake-color-surface` | 日历背景 | 对应的颜色 Props 可以覆盖单个实例的默认主题值。 # Cell 单元格 Cell 组件由 `CellItem` 和 `CellGroup` 组成:前者用于展示单条信息或入口,后者负责将多条内容组织为带标题和外边框的分组。推荐两者搭配使用;`CellItem` 也可以独立使用。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 自定义内容与交互 `title`、`value`、`label` 为空时可使用同名插槽;点击回调携带 `index`,便于识别条目。 ```vue ``` ## 分组标题与边框 `CellGroup` 的 `title` 用于展示分组标题,`border` 控制分组内容上下边框。它可以包裹 `CellItem`,也可包裹其他任意内容。 ```vue ``` ## 作为页面入口 将跳转逻辑放在 `click` 中,使用 `index` 区分条目;纯展示项关闭箭头并避免绑定点击。 ```vue ``` ## API ### Props #### CellGroup Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | -------------------- | --------------------------- | ------ | | `title` | 分组标题 | `string` | `''` | | `border` | 是否显示分组上下边框 | `boolean` | `true` | | `titleStyle` | 分组标题样式 | `object \| array` | `{}` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | #### CellItem Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------------ | ----------------------------- | --------------------------- | ------------------------ | | `icon` | 左侧图标名称或图片地址 | `string` | `''` | | `title` / `value` / `label` | 标题、右侧内容、标题下方描述 | `string \| number` | `''` | | `borderBottom` | 是否显示下边框 | `boolean` | `true` | | `borderTop` | 是否显示上边框 | `boolean` | `false` | | `hoverClass` | 点击反馈类名 | `string` | `snake-cell-item--hover` | | `arrow` | 是否显示右侧箭头 | `boolean` | `true` | | `arrowDirection` | 右侧箭头方向 | `right \| up \| down` | `right` | | `center` | 内容是否垂直居中 | `boolean` | `false` | | `required` | 是否显示左侧必填星号 | `boolean` | `false` | | `titleWidth` | 标题宽度,数值按 rpx 处理 | `number \| string` | `''` | | `titleStyle` / `valueStyle` / `labelStyle` | 标题、内容、描述样式 | `object \| array` | `{}` | | `bgColor` | 背景颜色 | `string` | `transparent` | | `index` | `click` 回调中标识条目的值 | `string \| number` | `''` | | `useLabelSlot` | 是否使用 `label` 插槽 | `boolean` | `false` | | `iconSize` | 左侧图标大小,数值按 rpx 处理 | `number \| string` | `34` | | `iconStyle` | 左侧图标样式 | `object \| array` | `{}` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Slots #### CellGroup Slots | 名称 | 说明 | | ------- | -------- | | default | 分组内容 | #### CellItem Slots | 名称 | 说明 | | ------------ | ------------------------------ | | default | 右侧内容(`value` 为空时启用) | | `icon` | 左侧图标 | | `title` | 左侧标题(`title` 为空时启用) | | `label` | 标题下方描述 | | `right-icon` | 右侧自定义内容 | ### Events | 事件名 | 触发时机 | 参数 | | ------- | -------------------- | ------- | | `click` | 点击 CellItem 时触发 | `index` | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | ---------------------------------------------- | | `--snake-color-text-secondary` | CellItem 标题默认颜色 | | `--snake-color-text-muted` | CellItem 内容、描述、图标及 CellGroup 标题颜色 | | `--snake-color-surface` | CellGroup 内容背景色 | | `--snake-color-border` | 条目和分组边框颜色 | | `--snake-color-error` | 必填标记颜色 | | `--snake-color-surface-muted` | 点击反馈背景色 | # 更新日志 本文件是 `@puresnake/snake-ui` 的唯一更新日志来源,遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 风格:条目按「新增 / 变更 / 修复」分类,版本号遵循[语义化版本](https://semver.org/lang/zh-CN/),日期为实际发布日。文档站的更新日志页面由 `pnpm changelog:sync` 从本文件单向同步生成。 ## [0.0.4] - 2026-10-30 ### 新增 - 公开子路径 `@puresnake/snake-ui/qrcode`:导出二维码矩阵生成器 `generateQRCode` / `QRErrorCorrectLevel`,供海报合成等离屏 canvas 场景直接取矩阵数据。`` 组件为屏上渲染,矩阵需求此前无法从包外获取。 ### 修复 - `exports` 补充 `./components/snake-cms/types` 显式入口:修复业务侧 `import type ... from '@puresnake/snake-ui/components/snake-cms/types'` 在 TypeScript bundler 解析下报 TS2307 的问题。 - 背景说明:TypeScript 对 `exports` 目标不做扩展名探测,也不支持中间通配(`*/types`),组件内部模块必须逐个显式声明。 ### 变更 - 开源仓库迁移至 GitHub 组织 [purenia-ai/snake-ui](https://github.com/purenia-ai/snake-ui),`repository` / `bugs` / `homepage` 等包元数据与文档链接同步更新。 ## [0.0.3] - 2026-10-29 ### 修复 - `exports` 深层路径对 TypeScript / Vite 的兼容性:`./libs/request`、`./libs/runtime` 提供显式入口;`./libs/config/*`、`./libs/cms/*`、`./libs/function/*`、`./libs/hooks/*` 映射到显式 `.ts` 文件。TypeScript 不做扩展名探测,通配 `./libs/*` 下的无扩展名路径此前无法解析。 ## [0.0.2] - 2026-10-29 ### 新增 - `package.json` 补齐 `exports` 子路径:`./libs/*`、`./plugins/*`、`./locale/*`、`./iconfont.css`,接入方可以直接通过 `@puresnake/snake-ui/libs/...` 等子路径 import。 - 新增 `pnpm changelog:sync` 脚本:本文件单向同步到 `docs/components/changelog.md`,文档站更新日志随发版自动对齐。 ## [0.0.1] - 2026-10-29 ### 新增 - 首个 npm 公开发布版本(MIT)。基于 Vue 3 + TypeScript 的 uni-app 组件库,面向商城与 CMS 场景。 - 46 个通用组件,覆盖基础、表单、数据、反馈、布局、导航等分类,easycom 按需引入。 - 14 个配置驱动的 CMS 页面区块,统一由 `snake-cms` 渲染。 - 内置明暗主题(`theme.scss`)、`zh-CN` / `en-US` 多语言、基于 `uni.request` 的 HTTP 客户端与常用 hooks / 工具。 - 兼容 H5、微信小程序、支付宝小程序、App 等多端。 --- ## 组件索引 以下清单随组件目录更新,当前共 46 个通用组件入口。 基础组件(12) - Parse 富文本解析 - ConfigProvider 全局配置 - Button 按钮 - Icon 图标 - Image 图片 - QrCode 二维码 - Loading 加载 - Skeleton 骨架屏 - Transition 过渡动画 - RootPortal 根节点传送 - Text 文本 - Link 超链接 表单组件(11) - Form 表单 - Input 输入框 - Textarea 文本域 - Checkbox 复选框 - Radio 单选框 - Switch 开关 - Slider 滑动选择器 - Search 搜索框 - Select 列表选择器 - Upload 文件上传 - Calendar 日历 数据组件(5) - Loadmore 加载更多 - LineProgress 线形进度条 - ReadMore 阅读更多 - Empty 空状态 - CountDown 倒计时 反馈组件(5) - NoticeBar 通知栏 - Overlay 遮罩层 - Tooltip 文字提示 - Popup 弹出层 - NoNetwork 无网络提示 布局组件(4) - Swiper 轮播图 - Sticky 吸顶 - Line 分隔线 - Cell 单元格 导航组件(9) - Navbar 导航栏 - Tabbar 底部导航栏 - Tabs 标签页 - Subsection 分段器 - ButtonSort 排序按钮 - DropMenu 下拉菜单 - IndexList 索引列表 - IndexListPanel 容器索引列表 - IndexAnchor 索引锚点 # Checkbox 复选框 `Checkbox` 支持独立 `v-model` 布尔绑定,也可放入 `CheckboxGroup` 通过 `name` 管理数组值;`CheckboxGroup` 提供最大选择数与布局控制。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 独立模式直接绑定布尔值;组模式通过 `CheckboxGroup` 的 `v-model` 管理选中数组: ```vue 同意用户协议 苹果 雪梨 ``` 布局通过 `width` 与 `wrap` 控制:`width` 指定每个 checkbox 的占宽(需带单位,如 `width="240rpx"`),`wrap` 让每个 checkbox 单独占一行。 ## 表单值与数量限制 组模式的 `v-model` 始终是 `name` 数组。达到 `max` 后,其余未选项不可再选;业务应根据数组值提交,而不是读取展示文本。 ```vue 读取 编辑 管理 ``` ## API ### CheckboxGroup #### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ---------------------------- | ---------------------- | ---------- | | `modelValue` | 选中的 name 数组 | `(string \| number)[]` | - | | `max` | 最多能选中多少个 | `number` | `999` | | `disabled` | 全组禁用 | `boolean` | `false` | | `name` | 表单内提交时的标识符 | `boolean \| string` | `''` | | `labelDisabled` | 是否禁止点击标签选中 | `boolean` | `false` | | `shape` | square/circle 形状 | `string` | `'square'` | | `activeColor` | 选中状态下的颜色 | `string` | 主题色 | | `size` | 整体尺寸 small/default/large | `string` | `''` | | `width` | 每个 checkbox 占组宽度 | `string` | `'auto'` | | `wrap` | 是否每个 checkbox 都换行 | `boolean` | `false` | | `iconSize` | 勾号大小,单位 rpx | `UnitValue` | `''` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | #### Events `update:modelValue` 和 `change` 均返回最新选中数组。 #### Slots 默认插槽放置 Checkbox。 ### Checkbox #### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ------------------------------------ | ------------------ | ------------ | | `modelValue` | 是否选中,支持 v-model | `boolean` | `false` | | `name` | 数据项标识符 | `string \| number` | `''` | | `label` | 展示标签文本 | `string` | `''` | | `shape` | square/circle 形状 | `string` | 继承 Group | | `disabled` / `labelDisabled` | 禁用 / 禁止点击标签选中 | `boolean` | `false` | | `activeColor` | 选中颜色,设置后覆盖父级 activeColor | `string` | 主题色 | | `iconSize` / `labelSize` | 勾号与标签字号,单位 rpx | `UnitValue` | 按 size 预设 | | `size` | 整体尺寸 small/default/large | `string` | 继承 Group | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | #### Events | 事件名 | 说明 | 参数 | | ------------------- | ------------ | --------- | | `update:modelValue` | 选中状态更新 | `checked` | | `change` | 选中状态变化 | `checked` | #### Slots 默认插槽用于标签内容。 ## 主题变量 | 变量 | 用途 | | --------------------------- | ---------------------- | | `--snake-color-primary` | 默认选中颜色 | | `--snake-color-border` | 未选中和禁用边框 | | `--snake-color-disabled-bg` | 禁用状态背景与图标颜色 | | `--snake-color-text` | 标签文字颜色 | `activeColor` 会覆盖当前实例或分组的默认主题色。 ## 类型定义 从包根导入 `CheckboxGroupProps`、`CheckboxProps` 与 `CheckboxEmits`。 # Color 色彩 Snake UI 用统一的色彩 token 表达品牌、状态、文字与界面层级。组件优先读取 CSS 变量,因此主题或明暗模式切换时无需逐个改色。 ## 主题颜色 `primary` 是 Snake 绿,代表品牌和主要操作;`dark`、`disabled`、`light` 分别用于按压、禁用和浅底状态。 辅助色表达固定业务语义:成功、警告、错误和普通信息,不应仅因视觉偏好互换。 ## 文本与界面
{{ color.name }}--snake-color-{{ color.token }}{{ color.value }}
页面使用 `background`,卡片和面板使用 `surface`,轻量分区使用 `surface-muted`;外框使用 `border`,内容分隔使用 `divider`。Snake UI 的页面背景为 `#F6F6F6`。 ## 遮罩与阴影 | Token | 默认值 | 用途 | | --------------------------------------------- | --------------------- | -------- | | `--snake-color-mask` | `rgba(0, 0, 0, 0.4)` | 弹层遮罩 | | `--snake-color-shadow` | `rgba(0, 0, 0, 0.1)` | 浮层阴影 | | `--snake-color-white` / `--snake-color-black` | `#FFFFFF` / `#000000` | 纯色对比 | ## 在样式与脚本中使用 ```scss .action { color: var(--snake-color-primary-ink); background: var(--snake-color-primary); &:active { background: var(--snake-color-primary-dark); } &:disabled { background: var(--snake-color-primary-disabled); } } ``` ```ts import { useTheme } from '@puresnake/snake-ui'; const { color } = useTheme(); console.log(color.primary, color.text); ``` ::: tip 多主题与暗黑模式 通过 `--snake-color-*` 或 `color` 读取颜色,不要在业务代码复制暗色值。主题配置方式见[多主题与暗黑模式](/guide/multi-theme)。 ::: # 内置样式 Snake UI 的 `index.scss` 内置了一组常用布局工具类,适合页面中的少量、重复性布局。组件功能本身不依赖你主动使用这些类。 ::: tip 使用 npm 时引入 `@puresnake/snake-ui/index.scss`;使用 `uni_modules` 时引入项目内对应的 `index.scss`。具体配置见[配置](/components/setting)。 ::: ## 定位 ```html 绝对定位内容 ``` | 类名 | 样式 | | --- | --- | | `snake-relative`、`snake-rela` | `position: relative` | | `snake-absolute`、`snake-abso` | `position: absolute` | ## 字号 语义字号包含 `snake-font-xs`、`snake-font-sm`、`snake-font-md`、`snake-font-lg` 和 `snake-font-xl`,对应 `22rpx`、`26rpx`、`28rpx`、`30rpx` 和 `34rpx`。 还可以使用数值形式: - `snake-font-9` 至 `snake-font-19` 使用 `px`。 - `snake-font-20` 至 `snake-font-40` 使用 `rpx`。 ```html 辅助文字 标题文字 ``` ## Flex 布局 常用类包括: - `snake-flex`:横向 Flex 并垂直居中。 - `snake-flex-center`:水平垂直居中。 - `snake-flex-col`:纵向 Flex。 - `snake-flex-wrap`、`snake-flex-nowrap`:换行或不换行。 - `snake-col-top`、`snake-col-center`、`snake-col-bottom`:垂直对齐。 - `snake-row-left`、`snake-row-center`、`snake-row-right`:水平对齐。 - `snake-row-between`、`snake-row-around`:分布方式。 子元素可以使用 `snake-flex-0` 至 `snake-flex-12` 设置 `flex` 值。 ## 文字对齐与显隐 - `snake-text-left`、`snake-text-center`、`snake-text-right` 控制文字对齐。 - `snake-hidden` 同时设置 `opacity: 0` 和 `visibility: hidden`,仍会保留元素布局空间。 ## 内外边距 间距数值范围为 `0` 至 `80rpx`,其中偶数和 5 的倍数可用。 - 四周外边距:`snake-margin-20`、`snake-m-20`。 - 四周内边距:`snake-padding-20`、`snake-p-20`。 - 指定方向外边距:`snake-margin-left-20`、`snake-m-l-20`。 - 指定方向内边距:`snake-padding-top-20`、`snake-p-t-20`。 方向缩写为 `l`、`t`、`r`、`b`。大面积视觉定制应使用主题变量或业务类名,参见[自定义样式](/guide/custom-style)。 # ConfigProvider 全局配置 `snake-config-provider` 是 Snake UI 主题系统的页面入口组件,负责把当前主题的 CSS 变量注入页面,并根据主题模式附加明亮或暗黑类名。将它与 `Root` 插件配合使用,可以让主题配置自动作用于每个页面,无需逐页添加组件。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基本用法 直接包裹页面内容后,内部组件即可使用当前主题的 CSS 变量: ```vue ``` ## 配合虚拟根组件 uni-app 没有可直接包裹所有页面的应用级根组件。推荐在 `src/App.root.vue` 中保留页面插槽,再通过 `Root` 插件为每个页面自动注入全局根组件。 ```vue ``` 在 `vite.config.ts` 中启用插件: ```ts import { defineConfig } from 'vite'; import Uni from '@dcloudio/vite-plugin-uni'; import { Root } from './src/uni_modules/snake-ui/plugins'; export default defineConfig({ plugins: [Root(), Uni()] }); ``` `` 是页面内容的渲染位置,必须保留。配置完成后需要重新启动开发服务,插件会在构建阶段完成根组件注册和页面包裹。 ## 指定主题与暗黑模式 组件默认只注入主题变量,不会改变当前主题。需要由外层控制主题时,可以传入已注册的主题名和暗黑模式: ```vue ``` `current-theme` 必须对应通过 `app.use(SnakeUI, { theme })` 注册的主题名。`dark-mode="auto"` 会在平台支持时跟随系统主题。 ## 监听配置同步 当 `current-theme` 或 `dark-mode` props 促使组件切换主题时,会分别触发 `theme-change` 和 `mode-change`: ```vue ``` 这两个事件描述的是组件对 props 的同步结果。通过 `setTheme()`、`setDarkMode()` 或 `useTheme()` 在组件外部切换主题时,请直接监听对应的响应式状态。 ## 工作原理 - 组件把主题引擎生成的 CSS 变量以内联样式写入根节点,确保变量在 H5 和小程序中都能向页面内容传递。 - 根节点会附加 `snake-theme-light` 或 `snake-theme-dark` 类名,以及 `data-snake-theme-mode` 属性,便于编写模式相关样式。 - `current-theme` 和 `dark-mode` 变化时,组件会把新值同步到主题引擎并持久化。 - 不传控制 props 时,组件只负责变量注入,主题状态仍由全局主题 API 管理。 ## 常见场景 - **应用全局主题**:在 `App.root.vue` 中使用一次,并配合 `Root` 自动覆盖所有页面。 - **独立页面入口**:不启用根组件插件时,在需要主题变量的页面外层显式包裹。 - **受控主题设置**:由设置页维护主题名和暗黑模式,通过 props 同步到主题引擎。 - **局部样式扩展**:使用 `custom-class` 或 `custom-style` 补充根节点布局,同时继续继承主题变量。 ::: tip 主题状态 组件负责让主题变量进入页面。注册主题、主动切换主题以及读取响应式色板,请使用 [`useTheme()` 和主题 API](/guide/multi-theme)。 ::: ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | -------------- | -------------------------------------------- | ---------------------------------- | ------ | | `darkMode` | 暗黑模式;变化时同步到主题引擎 | `'light' \| 'dark' \| 'auto'` | — | | `currentTheme` | 已通过 `app.use` 注册的主题名 | `string` | `''` | | `customClass` | 添加到根节点的自定义类名 | `string` | `''` | | `customStyle` | 添加到根节点的自定义样式,与主题变量样式合并 | `string \| Record` | `''` | ### Events | 事件名 | 说明 | 回调参数 | | -------------- | ---------------------------------- | --------------------------- | | `theme-change` | `currentTheme` prop 成功同步时触发 | `(themeName: string)` | | `mode-change` | `darkMode` prop 成功同步时触发 | `(mode: 'light' \| 'dark')` | ### Slots | 插槽名 | 说明 | | --------- | -------------------------- | | `default` | 需要应用主题变量的页面内容 | ## 类型定义 ```ts import type { ConfigProviderEmits, ConfigProviderProps } from '@puresnake/snake-ui'; ``` ## 主题变量 组件注入当前 Snake UI 主题生成的全部 `--snake-*` 变量;变量清单与生成方式见[多主题与暗黑模式](/guide/multi-theme)。 最低版本:`0.1.0` # CountDown 倒计时 用于活动截止等场景的倒计时,通过数字变化给用户明确的时间感受,提示用户进行某行为操作。支持时分秒显示开关、冒号与中文单位分隔符、数字块样式定制。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` `timestamp` 单位为秒;组件挂载后自动开始,每秒触发一次 `change`(参数为剩余秒数),归零时触发 `end`。 ## 显示控制与样式 ```vue ``` - `separator="colon"` 用英文冒号连接,`separator="zh"` 在每个数字后追加中文单位(天/时/分/秒,英文环境下为 d/h/m/s)。 - `show-days="false"` 时天数折算进小时;`hide-zero-day` 在天数为 0 时隐藏天部分。 - `height` 同时设置数字块的宽高;`show-border` 打开数字边框。 - `autoplay="false"` 时不自动开始,通过 ref 调用 `start()`;`end()` 可提前结束。 ## 服务端截止时间 业务通常拿到的是截止时间戳,应先在页面计算剩余秒数再传入,避免将毫秒直接传给 `timestamp`。页面重新进入时重新计算,可避免后台停留造成显示不准。 ```ts const remaining = Math.max(0, Math.floor((endAt - Date.now()) / 1000)); ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | -------------------------------------------------------- | --------------------------- | --------------------------- | -------------------- | | `timestamp` | 倒计时剩余秒数 | `number \| string` | `0` | | `autoplay` | 挂载后自动开始 | `boolean` | `true` | | `separator` | 分隔符形态 | `string` | `colon` | | `separatorSize` / `separatorColor` | 分隔符大小与颜色 | `number \| string / string` | `30` / 主题文字色 | | `color` / `fontSize` | 数字颜色与大小(rpx) | `string / number \| string` | 主题文字色 / `30` | | `bgColor` / `height` | 数字背景与数字块宽高(rpx) | `string / number \| string` | 主题表面色 / `auto` | | `showBorder` / `borderColor` | 数字边框开关与颜色 | `boolean / string` | `false` / 主题文字色 | | `showDays` / `showHours` / `showMinutes` / `showSeconds` | 各部分显示开关 | `boolean` | `true` | | `hideZeroDay` | 天数为 0 时隐藏天部分 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名与样式 | `string / style` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | -------- | ---------------- | -------- | | `change` | 每秒更新剩余时间 | 剩余秒数 | | `end` | 倒计时归零或结束 | - | ### Expose | 方法 | 说明 | | --------- | ------------------ | | `start()` | 开始或继续倒计时 | | `end()` | 提前结束当前倒计时 | ## 类型定义 ```ts import type { CountDownProps, CountDownEmits, CountDownExpose } from 'snake-ui'; ``` ## 主题变量 | 变量名 | 说明 | | ----------------------- | ---------------------- | | `--snake-color-text` | 数字、分隔符和边框颜色 | | `--snake-color-surface` | 数字块背景色 | # DropMenu 下拉菜单 `DropMenu` 与 `DropMenuItem` 成对使用:容器负责多个菜单项的布局、互斥展开和弹层定位,菜单项提供触发器、遮罩与内容面板。面板打开前会真实测量菜单底部位置,适用于普通布局和吸顶布局。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 `DropMenuItem` 必须作为 `DropMenu` 的直接子组件使用,每个菜单项通过 `v-model` 独立绑定选中值: ```vue ``` ## 自定义面板 可以在菜单项默认插槽中放入自定义筛选表单,配合 `beforeToggle` 在展开前校验: ```ts const beforeToggle = ({ resolve }) => resolve(userHasPermission); ``` ```vue 自定义筛选内容 ``` ## 吸顶与动态内容 菜单进入吸顶状态、窗口尺寸变化或异步面板内容改变后,调用实例方法 `updateDropMenuRect()` 重新测量面板顶部位置。通过容器实例调用 `open(index)` 可由外部操作打开指定菜单。 ```vue 选择排序 ``` ## API ### DropMenu #### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------------------- | -------------------- | --------------------------- | -------------------- | | `activeColor` / `inactiveColor` | 激活和默认标题颜色 | `string` | 主题色 / 正文色 | | `closeOnClickMask` | 点击遮罩关闭 | `boolean` | `true` | | `closeOnClickSelf` | 再次点击当前标题关闭 | `boolean` | `true` | | `duration` | 面板动画时长,ms | `number` | `300` | | `height` | 菜单栏高度 | `string \| number` | `40` | | `borderBottom` | 是否显示底边 | `boolean` | `false` | | `titleSize` / `menuIcon` / `menuIconSize` | 标题字号、图标和尺寸 | `string \| number` | `28` / `down` / `18` | | `zIndex` | 菜单和弹层层级基准 | `number` | `985` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | #### Events | 事件名 | 触发时机 | 参数 | | ------- | -------------- | ---------- | | `open` | 某个菜单项展开 | 菜单项索引 | | `close` | 某个菜单项关闭 | 菜单项索引 | #### Expose | 方法 | 说明 | | ------------------------ | --------------------------------- | | `open(index)` | 展开指定项 | | `close()` / `colseAll()` | 关闭当前项;colseAll 保留历史拼写 | | `highlight(index?)` | 只高亮指定标题,不展开面板 | | `updateDropMenuRect()` | 主动重新测量菜单位置 | ### DropMenuItem #### Props | 参数 | 说明 | 类型 | 默认值 | | -------------- | ------------------------------------------------ | --------------------------- | ------- | | `modelValue` | 当前选中值,支持 v-model | `unknown` | - | | `title` | 固定标题;为空时显示选中项 label | `string` | `''` | | `options` | `{ label, value, disabled? }[]` | `array` | `[]` | | `disabled` | 是否禁用菜单项 | `boolean` | `false` | | `height` | 面板最大高度或 auto | `string \| number` | `auto` | | `show` | 外部强制显示面板 | `boolean` | - | | `beforeToggle` | 展开前回调,通过 `resolve(boolean)` 决定是否展开 | `function` | - | | `customStyle` | 面板自定义样式 | `string \| object \| array` | `''` | #### Events | 事件名 | 触发时机 | 参数 | | ------------------- | ------------ | ---------- | | `update:modelValue` | 选择可用选项 | 选项 value | | `change` | 选择可用选项 | 选项 value | | `open` | 面板展开 | - | | `close` | 面板关闭 | - | #### Slots | 插槽名 | 说明 | | --------- | ---------------------- | | `default` | 替换自动生成的选项列表 | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | ---------------------- | | `--snake-color-primary` | 激活标题和选中项颜色 | | `--snake-color-text-secondary` | 默认标题及选项文字颜色 | | `--snake-color-surface` | 菜单栏和下拉面板背景色 | | `--snake-color-divider` | 菜单栏及选项分隔线颜色 | | `--snake-color-shadow` | 下拉面板阴影颜色 | # Empty 空状态 用于列表、搜索结果或异常页面没有内容时提供统一反馈。内置多种语义模式,也支持图片、图标和插槽定制。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 自定义图片与操作区 ```vue ``` `src` 和 `icon` 均可覆盖模式图标;`src` 更适合图片地址,`icon` 可传 Icon 名称。 ## 加载、错误与空数据 空状态应只在请求完成且结果为空时显示;加载中使用 Skeleton 或 Loading,请求失败则优先提供重试操作,避免把失败误导为“暂无数据”。 ```vue ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | --------------------- | ---------------------------------------------------------------------------------------------- | --------------------------- | ------------ | | `show` | 是否显示 | `boolean` | `true` | | `mode` | 语义模式:data/list/search/page/order/coupon/favor/permission/history/message/wifi/address/car | `string` | `data` | | `src` | 自定义图片地址 | `string` | `''` | | `icon` | 自定义图标名或图片地址 | `string` | `''` | | `iconColor` | 图标颜色 | `string` | 主题弱文本色 | | `iconSize` | 图标或图片尺寸 | `string \| number` | `120` | | `text` | 提示文字;为空时使用模式默认文案 | `string` | `''` | | `color` / `textColor` | 文字颜色,textColor 优先 | `string` | 主题弱文本色 | | `fontSize` | 文字大小 | `string \| number` | `26` | | `marginTop` | 组件顶部外边距 | `string \| number` | `0` | | `customClass` | 自定义类名 | `string` | `''` | | `customStyle` | 根容器样式 | `string \| object \| array` | `''` | ### Slots | 插槽名 | 说明 | | --------- | ---------------------- | | `icon` | 完全替换默认图片或图标 | | `default` | 替换默认提示文字 | | `bottom` | 文字下方操作区 | ## 主题变量 | 变量 | 用途 | | -------------------------- | ---------------- | | `--snake-color-text-light` | 默认图标颜色 | | `--snake-color-text-muted` | 默认提示文字颜色 | `iconColor`、`color` 和 `textColor` 可以覆盖单个实例的颜色。 # Form 表单 `Form` 用于管理表单模型和规则,`FormItem` 负责字段布局、校验状态与错误展示。组件行为与 uView Pro Form 保持一致。 ## 使用建议 Form 负责字段关系和提交校验,不负责发送请求。将 API 调用、提交中状态和失败重试保留在业务页面,规则中的字段路径必须与 `model` 一致。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ```ts const valid = await formRef.value.validate(); if (valid) { // 提交 model } ``` 规则支持 `required`、`type`、`min`、`max`、`len`、`pattern`、`enum`、`transform`、`validator`、`asyncValidator`、`fields` 和 `defaultField`。字段 `prop` 支持 `profile.name`、`accounts.0.name` 等嵌套路径。 ## 校验与提交 将 `rules` 与 `model` 的字段路径保持一致。`validate()` 返回 `true` 才执行提交;提交期间应由业务自行锁定提交按钮,避免重复请求。 ```vue 提交 ``` ```ts const rules = { mobile: [ { required: true, message: '请输入手机号', trigger: ['blur', 'change'] }, { pattern: /^1\d{10}$/, message: '手机号格式不正确', trigger: 'blur' } ] }; async function submit() { if (!(await formRef.value?.validate())) return; await saveProfile(model); } ``` ## 动态深层校验 ```ts const rules = { accounts: { type: 'array', required: true, defaultField: { type: 'object', fields: { name: { required: true, message: '请输入账户名', trigger: ['change', 'blur'] } } } } }; ``` 对应动态字段使用 `prop="accounts.0.name"`。组件会从 `accounts.defaultField.fields.name` 查找规则。 ## 错误提示 `errorType` 是数组,可组合以下值: - `message`:字段下方显示错误文字。 - `toast`:全表校验时提示第一个错误。 - `border-bottom`:字段底边变为错误色。 - `border`:内部输入控件边框变为错误色。 - `none`:隐藏全部错误提示。 ## 无障碍 - 每个可编辑字段都应通过 `FormItem` 提供可见标签,必填状态不能只依赖颜色。 - 错误信息需要说明修正方式;提交失败后应聚焦或滚动到第一个无效字段。 - 提交请求开始后显示加载状态,完成或失败后恢复操作并保留用户输入。 ## API ### Form Props | 参数 | 说明 | 类型 | 默认值 | | --------------- | ------------------------ | --------------------------- | ---------------------- | | `model` | 表单数据对象 | `object` | `{}` | | `rules` | 校验规则 | `FormRules` | `{}` | | `errorType` | 错误提示方式 | `FormErrorType[]` | `['message', 'toast']` | | `borderBottom` | 表单项默认显示底边 | `boolean` | `true` | | `labelPosition` | 标签位置 | `left \| top` | `left` | | `labelWidth` | 标签宽度,数字单位为 rpx | `string \| number` | `90` | | `labelAlign` | 标签对齐 | `left \| center \| right` | `left` | | `labelStyle` | 标签样式 | `object` | `{}` | | `size` | 表单尺寸 | `small \| default \| large` | `default` | ### Form Expose | 方法 | 说明 | | --------------------------------- | ----------------------------------------------- | | `setRules(rules)` | 动态替换规则 | | `resetFields()` | 重置全部已注册字段 | | `validate(callback?)` | 校验全部字段,返回 `Promise` | | `validateField(props, callback?)` | 校验一个或多个指定字段,返回 `Promise` | ### Form Slots | 名称 | 说明 | | --------- | ---------- | | `default` | 表单项内容 | ### FormItem Props | 参数 | 说明 | 默认值 | | ------------------------------------------------------------ | --------------------------------- | --------- | | `label` / `prop` | 标签和模型字段路径 | `''` | | `required` | 仅显示必填星号 | `false` | | `borderBottom` | 是否显示底边;空字符串时继承 Form | `''` | | `labelPosition` / `labelWidth` / `labelAlign` / `labelStyle` | 标签布局;未设置时继承 Form | - | | `leftIcon` / `rightIcon` | 左右图标 | `''` | | `leftIconPrefix` / `rightIconPrefix` | 自定义图标类前缀 | `sicon` | | `leftIconStyle` / `rightIconStyle` | 图标样式 | `{}` | | `size` | small/default/large 或自定义字号 | 继承 Form | ### FormItem Slots | 名称 | 说明 | | ----------- | -------------------- | | `default` | 表单控件 | | `label` | 自定义标签内容 | | `leftIcon` | 自定义左侧图标 | | `rightIcon` | 自定义右侧图标 | | `right` | 表单项最右侧扩展内容 | ### FormItem Expose `validation(trigger?, callback?)`、`resetField()`、`onFormBlur()`、`onFormChange()`。 ## 主题变量 Form 容器没有独立视觉令牌,FormItem 直接使用以下全局变量: | 变量 | 用途 | | -------------------------- | ------------------ | | `--snake-color-text` | 标签文字颜色 | | `--snake-color-text-light` | 辅助文字颜色 | | `--snake-color-divider` | 表单项分隔线 | | `--snake-color-error` | 必填标记和错误状态 | # Icon 图标 `snake-icon` 支持内置字体图标、图片图标、标签和百分比裁切效果。内置字体的类名前缀为 `sicon`,图标名称与下方图标集中的名称一一对应。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` `name` 中包含 `/` 时按图片图标渲染。字体图标会生成 `sicon-${name}` 类名,例如 `name="search"` 对应 `sicon-search`。自定义字体图标可通过 `custom-prefix` 指定字体类前缀。 图片图标请同时设置明确的 `width` 与 `height`;部分填充效果使用 `percent`(0–100)与 `inactive-color`,适合评分、进度等场景。 ## 图标集 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------------------------------------- | --------------------------------------- | ------------------ | ------------------------ | | `name` | 图标名称或图片地址 | `string` | `''` | | `color` | 图标颜色,可使用主题色名称 | `string` | `''` | | `size` | 图标尺寸,数值单位为 rpx | `string \| number` | `inherit` | | `bold` | 是否加粗 | `boolean` | `false` | | `index` | 点击和触摸事件返回的标识 | `string \| number` | `''` | | `hoverClass` | 按下时的样式类 | `string` | `''` | | `customPrefix` | 自定义字体类前缀 | `string` | `sicon` | | `label` / `labelPos` | 标签及其位置 | 多类型 | `''` / `right` | | `labelSize` / `labelColor` | 标签字号及颜色 | 多类型 | `28` / 主题文本色 | | `space` | 标签和图标的统一间距,优先于四向 margin | `string \| number` | `''` | | `marginLeft` / `marginTop` / `marginRight` / `marginBottom` | 各标签方向的默认间距 | `string \| number` | `6` | | `imgMode` / `width` / `height` | 图片图标参数 | 多类型 | `widthFix` / `''` / `''` | | `top` | 垂直位置微调 | `string \| number` | `0` | | `showDecimalIcon` | 是否显示部分填充图标 | `boolean` | `false` | | `inactiveColor` / `percent` | 裁切图标的底色及填充百分比 | 多类型 | 分割线色 / `50` | | `customClass` / `customStyle` | 自定义类名和根节点样式 | 多类型 | 空值 | ### Events | 事件名 | 触发时机 | 参数 | | ------------ | -------- | --------------------------- | | `click` | 点击图标 | `index`,未设置时为原始事件 | | `touchstart` | 触摸开始 | `index`,未设置时为原始事件 | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | ---------------------- | | `--snake-color-text-secondary` | 标签文字默认色 | | `--snake-color-divider` | DecimalIcon 未激活颜色 | | `--snake-color-primary` | primary 主题色 | | `--snake-color-success` | success 主题色 | | `--snake-color-warning` | warning 主题色 | | `--snake-color-error` | error 主题色 | | `--snake-color-info` | info 主题色 | # Image 图片 封装 uni-app `image`,提供加载、失败、淡入、圆角、圆形、WebP、长按菜单和图片预览能力。`src` 变化时会自动重置状态。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 加载状态 ### 加载中 默认显示加载图标。简单的品牌占位图可使用 `loading-img`;需要组合动画、文字或骨架屏时使用 `loading` 插槽。 ```vue ``` 传入 `show-loading="false"` 可隐藏加载反馈。 ### 加载失败 默认显示错误图标与提示。简单错误图使用 `error-img`;需要自定义内容时使用 `error` 插槽。 ```vue ``` 传入 `show-error="false"` 可隐藏失败反馈。两个状态的渲染优先级均为:同名插槽 > `loading-img` / `error-img` > 默认图标。 ## 视口懒加载 `lazy-load` 使用 `uni.createIntersectionObserver`,仅在进入视口预加载距离后创建真实图片请求。组件不会同时启用原生 `image` 的 `lazy-load`,避免两套懒加载调度相互影响。`loadingImg` 与 `errorImg` 在组件内部按状态直接渲染,未配置时才回退为默认图标;需要复杂状态内容时使用同名插槽,插槽优先。 ```vue ``` `lazy-threshold` 默认为 `100`;数值越大,图片会在距视口更远的位置开始请求。 ## 展示样式 ### 填充模式 通过 `mode` 控制图片在容器内的裁剪和对齐方式,常用商品图使用 `aspectFill`,完整展示图片使用 `aspectFit`。 ```vue ``` ### 圆形与圆角 ```vue ``` ## 图片预览 传入 `preview` 后,点击图片会调用 `uni.previewImage`。使用 `preview-urls` 可提供预览图集合;集合应包含当前 `src`。 ```vue ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | -------------------------------------------- | ---------------------- | --------------------------------- | ------------------- | | `src` / `mode` | 图片地址和裁剪方式 | `string` | `'' / scaleToFill` | | `alt` | 图片的可访问文本 | `string` | `''` | | `width` / `height` | 容器尺寸 | `string \| number` | `100% / auto` | | `shape` / `radius` | 形状和圆角 | `square\|circle / string\|number` | `square / 0` | | `lazyLoad` / `lazyThreshold` | 视口懒加载及预加载距离 | `boolean / number` | `false / 100` | | `webp` | 使用 WebP | `boolean` | `false` | | `showMenuByLongpress` | 长按显示识别菜单 | `boolean` | `false` | | `fade` / `duration` | 淡入及其时长 | `boolean / number` | `true / 300` | | `showLoading` / `loadingIcon` / `loadingImg` | 加载反馈与图片占位 | `boolean / string / string` | `true / '' / ''` | | `showError` / `errorIcon` / `errorImg` | 失败反馈与图片回退 | `boolean / string / string` | `true / image / ''` | | `preview` / `previewUrls` | 点击预览及图片集合 | `boolean / string[]` | `false` | | `bgColor` / `customClass` / `customStyle` | 背景和自定义样式 | 多类型 | 主题默认值 | ### Events | 事件名 | 触发时机 | 参数 | | ------- | ------------ | ------- | | `load` | 图片加载成功 | `event` | | `error` | 图片加载失败 | `event` | | `click` | 点击图片 | `event` | ### Methods | 方法名 | 说明 | 参数 | | -------- | ------------------------------------- | ---- | | `reload` | 按当前 `src` 和懒加载策略重新请求图片 | - | ### Slots | 插槽名 | 说明 | | --------- | ------------------ | | `loading` | 自定义加载状态 | | `error` | 自定义加载失败状态 | ## 主题变量 | 变量名 | 说明 | | ----------------------------- | -------------------------- | | `--snake-color-surface-muted` | 图片容器默认背景色 | | `--snake-color-text-muted` | 状态图标默认颜色 | | `--snake-image-status-color` | 加载状态文字与图标颜色 | | `--snake-image-error-color` | 加载失败状态文字与图标颜色 | # IndexAnchor 索引锚点 定义索引列表中的分组位置,可在页面型 `IndexList` 或容器型 `IndexListPanel` 中使用。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue Apple ``` ## 自定义内容 ```vue 热门城市 ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------- | -------------------------- | --------------------------- | ------- | | `index` | 对应父级 indexList 的值 | `string \| number` | 必填 | | `text` | 展示文字;为空时显示 index | `string` | `''` | | `useSlot` | 是否优先使用默认插槽 | `boolean` | `false` | | `customClass` | 自定义类名 | `string` | `''` | | `customStyle` | 锚点自定义样式 | `string \| object \| array` | `''` | ### Slots | 插槽名 | 说明 | | --------- | -------------------------- | | `default` | useSlot 为 true 时替换文字 | ## 主题变量 | 变量名 | 说明 | | -------------------------- | ------------ | | `--snake-color-text` | 锚点文字颜色 | | `--snake-color-background` | 锚点背景颜色 | # IndexListPanel 容器索引列表 用于弹窗、抽屉和定高区域的索引列表。组件内部创建 `scroll-view`,不依赖页面滚动位置。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 父容器必须提供确定高度。 ```vue Apple Banana ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | -------------------- | --------------------------- | ----------------- | | `indexList` | 右侧索引值 | `Array` | `[]` | | `scrollTop` | 内部容器目标滚动位置 | `number \| string` | `0` | | `zIndex` | 索引栏和吸顶锚点层级 | `number` | `965` | | `sticky` | 锚点是否吸顶 | `boolean` | `true` | | `offsetTop` | 容器内吸顶偏移 | `string \| number` | `0` | | `activeColor` / `inactiveColor` | 当前和默认索引颜色 | `string` | 主题色 / 弱文本色 | | `railStyle` | 右侧索引栏样式 | `string \| object \| array` | `''` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | -------- | ------------------ | ------------------ | | `select` | 点击或拖动选择索引 | 索引值 | | `change` | 当前分组变化 | `{ index, value }` | ### Expose | 方法 | 说明 | | ------------------------ | -------------------------- | | `scrollTo(indexOrValue)` | 滚动到序号或索引值 | | `update()` | 内容尺寸变化后重新测量锚点 | ### Slots | 插槽名 | 说明 | | --------- | ------------------------ | | `default` | 索引锚点及对应的分组内容 | ## 主题变量 | 变量名 | 说明 | | ----------------------------- | ---------------------- | | `--snake-color-primary` | 当前索引默认颜色 | | `--snake-color-text-muted` | 未激活索引默认颜色 | | `--snake-color-primary-light` | 当前索引提示层背景颜色 | # IndexList 页面索引列表 跟随页面滚动,通过右侧索引快速定位分组内容,与 `IndexAnchor` 配合使用。 如果列表位于弹窗、抽屉或定高区域,请使用 [`IndexListPanel`](./index-list-panel.md)。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 页面需要在 `onPageScroll` 中记录滚动位置并传给组件。 ```vue ``` ## 偏移与异步数据 页面有固定导航栏时传入 `offset-top`,让索引跳转和吸顶锚点避开导航栏。异步加载、折叠展开或图片加载改变了分组高度后,等待视图更新并调用 `update()` 重新测量。 ```ts groups.value = await getContacts(); await nextTick(); indexListRef.value?.update(); ``` 点击索引会触发 `select`,页面滚动导致当前分组改变会触发 `change`;业务只需处理选中态或辅助提示,滚动定位由组件完成。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | ---------------------- | --------------------------- | ----------------- | | `indexList` | 右侧索引值 | `Array` | `[]` | | `scrollTop` | 页面当前滚动位置 | `number \| string` | `0` | | `zIndex` | 索引栏和吸顶锚点层级 | `number` | `965` | | `sticky` | 锚点是否吸顶 | `boolean` | `true` | | `offsetTop` | 页面吸顶与滚动目标偏移 | `string \| number` | `0` | | `activeColor` / `inactiveColor` | 当前和默认索引颜色 | `string` | 主题色 / 弱文本色 | | `railStyle` | 右侧索引栏样式 | `string \| object \| array` | `''` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | 裸数字和 `rpx` 字符串按 rpx 处理,显式 `px` 字符串按像素处理。 ### Events | 事件名 | 触发时机 | 参数 | | -------- | ------------------------ | ------------------ | | `select` | 点击或拖动选择索引 | 索引值 | | `change` | 页面滚动导致当前分组变化 | `{ index, value }` | ### Expose | 方法 | 说明 | | ------------------------ | -------------------------- | | `scrollTo(indexOrValue)` | 页面滚动到序号或索引值 | | `update()` | 页面布局变化后重新测量锚点 | ### Slots | 插槽名 | 说明 | | --------- | ------------------------ | | `default` | 索引锚点及对应的分组内容 | ## 主题变量 | 变量名 | 说明 | | ----------------------------- | ---------------------- | | `--snake-color-primary` | 当前索引默认颜色 | | `--snake-color-text-muted` | 未激活索引默认颜色 | | `--snake-color-primary-light` | 当前索引提示层背景颜色 | ## 从旧版迁移 旧版 `snake-index-list` 内置 `scroll-view`。升级后,页面场景需要传入页面 `scrollTop`;原弹窗和定高容器场景改用 `snake-index-list-panel`。 # Input 输入框 基于 uni-app input,支持清空、密码显示、格式化、前后插槽和 Form 校验联动。 ## 使用建议 Input 适合单行内容。多行输入使用 [Textarea](/components/textarea),结构化选择优先使用 Select、Calendar 等选择组件,避免让用户手工输入可枚举值。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 中文、日文等输入法处于候选组合阶段时不会提前同步半成品内容;组合结束后再更新 `v-model` 并触发表单校验。 ## 格式化与确认键 `formatter` 应为同步且无副作用的函数;需要在每次输入时格式化使用 `format-trigger="input"`,仅在失焦时整理内容使用 `blur`。异步校验交给 Form 规则处理。 ```vue ``` ## 无障碍 - 在 `FormItem` 中提供明确的 `label`,不要只依赖 placeholder 表达字段含义。 - 根据内容设置 `type`、`confirm-type` 和长度限制,让软键盘与输入预期一致。 - 校验失败时保留具体错误信息,并让用户能够回到对应字段修正。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------------------------- | ----------------------------------------------------- | ------------------------------- | ----------------- | | `modelValue` | v-model 值 | `string \| number` | `''` | | `type` / `password` | text/number/idcard/digit/password/nickname 与密码模式 | `string \| boolean` | `text` | | `placeholder` / `placeholderStyle` / `placeholderColor` | 占位内容和样式 | `string` | 主题默认值 | | `maxlength` / `clearable` / `showPassword` | 最大长度、清空和密码切换 | `number \| boolean` | `140` / `false` | | `prefixIcon` / `suffixIcon` | 前后图标 | `string` | `''` | | `border` / `shape` / `size` | none/surround/bottom、square/circle、尺寸 | `string` | `none` / `square` | | `disabled` / `readonly` | 禁用和只读 | `boolean` | `false` | | `formatter` / `formatTrigger` / `trim` | 格式化函数、input/blur 时机、失焦去空格 | `function \| string \| boolean` | - | | `focus` / `cursor` / `selectionStart` / `selectionEnd` | 焦点与光标选择 | `boolean \| number` | 原生默认值 | | `confirmType` / `confirmHold` / `holdKeyboard` | 键盘确认配置 | `string \| boolean` | `done` / `false` | | `adjustPosition` / `cursorSpacing` | 键盘避让 | `boolean \| number` | `true` / `0` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | ### Events | 事件名 | 说明 | 参数 | | ---------------------------------------- | ---------------------- | ---------------- | | `update:modelValue` / `input` / `change` | 值更新、输入和失焦确认 | `value` | | `focus` / `blur` | 获取或失去焦点 | 原生事件 | | `confirm` | 点击键盘确认 | `(value, event)` | | `clear` / `click` | 清空、点击组件 | - / event | | `keyboardheightchange` | 键盘高度变化 | 原生事件 | ### Slots | 名称 | 说明 | | -------- | ------------------ | | `prefix` | 替换输入框前置图标 | | `suffix` | 替换输入框后置图标 | ## 主题变量 Input 复用全局主题令牌: | 变量 | 用途 | | --------------------------- | ------------------------- | | `--snake-color-text` | 输入文字颜色 | | `--snake-color-text-light` | 占位文字颜色 | | `--snake-color-text-muted` | 操作图标颜色 | | `--snake-color-disabled-bg` | 禁用背景色 | | `--snake-color-divider` | 默认边框颜色 | | `--snake-color-primary` | 聚焦边框颜色 | | `--snake-color-error` | 校验失败边框颜色 | | `--snake-radius-md` | `surround` 模式的圆角大小 | ## 类型定义 从包根导入 `InputProps` 与 `InputEmits`。`formatter` 应保持同步且无副作用,异步校验交给 Form 规则处理。 # 安装 Snake UI 支持 npm 包和 `uni_modules` 两种安装方式。请选择一种方式,避免项目同时存在两份组件库。 ## 环境要求 开始前需要一个可正常运行的 uni-app Vue 3 项目: | 依赖 | 要求 | | --- | --- | | Vue | `>= 3.4.0` | | uni-app | `>= 3.0.0` | | 样式处理 | 支持 SCSS 与 `rpx` | 普通 Vue Web 项目不等同于完整的 uni-app 运行环境。平台能力和业务依赖见[运行环境与能力边界](/guide/compatibility)。 ## npm 安装 使用项目已有的包管理器安装: ::: code-group ```bash [pnpm] pnpm add @puresnake/snake-ui ``` ```bash [npm] npm install @puresnake/snake-ui ``` ```bash [yarn] yarn add @puresnake/snake-ui ``` ::: npm 方式的插件、样式和组件路径都以 `@puresnake/snake-ui` 开头。 ## uni_modules 安装 将组件库目录放入宿主项目的 `uni_modules/snake-ui`: ```text 你的项目/ └─ uni_modules/ └─ snake-ui/ ├─ components/ ├─ index.ts ├─ index.scss └─ theme.scss ``` 本地方式的导入路径应指向项目内的 `uni_modules/snake-ui`,不要再安装或引用 npm 副本。 ## 下一步 安装完成后继续进行[工程配置](/components/setting)。 # 组件总览 Snake UI 提供覆盖基础交互、表单和商城装修场景的组件。输入组件英文名、中文名或文档路径,即时定位所需能力。 第一次使用 Snake UI?请依次完成[安装](/components/install)、[配置](/components/setting)和[快速上手](/components/quickstart),再从下方选择组件。 页面装修能力统一进入 [CMS 组件总览](/cms/overview);CMS 区块由 `` 按配置渲染,不作为独立 easycom 组件出现在下方目录。 # LineProgress 线形进度条 以线形进度展示操作或任务的当前进度,比如上传文件,支持主题色预设、条纹与百分比展示。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 条纹与预设 ```vue ``` 进度条内部默认展示百分比,通过 `show-percent="false"` 关闭;传入默认插槽可完全替换内部内容。 `percent` 会按 0–100 使用;上传场景将接口回调的进度直接传入即可,完成后再由业务切换成功状态或关闭进度条。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | --------------- | --------------------------------- | ------------------------------------------------ | ----------------------- | | `percent` | 进度百分比,数值 0-100 | `number \| string` | `0` | | `round` | 两端是否显示半圆形 | `boolean` | `true` | | `type` | 主题预设,设置后 activeColor 失效 | `primary \| success \| warning \| error \| info` | `''` | | `activeColor` | 激活部分的颜色 | `string` | `--snake-color-success` | | `inactiveColor` | 进度条的底色 | `string` | `--snake-color-divider` | | `showPercent` | 是否在进度条内部显示百分比 | `boolean` | `true` | | `height` | 进度条高度,数值按 rpx 处理 | `number \| string` | `28` | | `striped` | 是否显示激活部分的条纹 | `boolean` | `false` | | `stripedActive` | 条纹是否具有动态效果 | `boolean` | `false` | ### Slots | 名称 | 说明 | | ------- | ------------------------ | | default | 替换进度条内部默认百分比 | ## 主题变量 | 变量名 | 说明 | | -------------------------- | ------------------------- | | `--snake-color-divider` | 轨道默认颜色 | | `--snake-color-primary` | primary 预设颜色 | | `--snake-color-success` | 默认激活色及 success 预设 | | `--snake-color-warning` | warning 预设颜色 | | `--snake-color-error` | error 预设颜色 | | `--snake-color-info` | info 预设颜色 | | `--snake-color-white` | 进度文字颜色 | | `--snake-color-text-light` | 条纹装饰颜色 | # Line 分隔线 用于分隔内容块的线条,支持横向与竖向两种方向、半像素细线以及实线/虚线/圆点样式。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 方向与线型 ```vue ``` `hairLine` 默认开启,通过 `transform: scaleY/scaleX(0.5)` 实现跨端一致的半像素细线。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | -------------------------------------- | --------------------------- | ---------------------- | | `color` | 线条颜色 | `string` | `--snake-color-border` | | `length` | 长度,竖向表现为高度,可为百分比或 rpx | `string` | `100%` | | `direction` | 线条方向 | `row \| col` | `row` | | `hairLine` | 是否显示半像素细线条 | `boolean` | `true` | | `margin` | 与上下左右元素的间距 | `string` | `0` | | `borderStyle` | 线条类型 | `solid \| dashed \| dotted` | `solid` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ## 主题变量 | 变量名 | 说明 | | ---------------------- | ------------ | | `--snake-color-border` | 分隔线默认色 | # Link 超链接 超链接组件,不同平台有不同表现形式:App 平台通过内置浏览器打开,小程序把链接复制到粘贴板并提示,H5 中通过 `window.open` 打开链接。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 头条小程序不支持该位置的默认插槽渲染,请优先通过 `text` 传入链接文字;其他平台仍可使用默认插槽。 `defaultClick` 为 false 时点击只触发 `click` 事件并携带链接地址,由业务自行处理跳转。 小程序不会直接打开外部网页,而是复制链接并提示用户;需要站内跳转时关闭 `default-click`,在 `click` 中使用项目路由。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | -------------- | ---------------------------- | ------------------ | ----------------------- | | `text` | 超链接文字 | `string \| number` | `''` | | `color` | 文字颜色 | `string` | `--snake-color-primary` | | `fontSize` | 字体大小,数值按 rpx 处理 | `string \| number` | `28` | | `underLine` | 是否显示下划线 | `boolean` | `false` | | `href` | 要跳转的链接 | `string` | `''` | | `mpTips` | 小程序复制到粘贴板后的提示语 | `string` | 语言包默认值 | | `lineColor` | 下划线颜色,默认同文字颜色 | `string` | `''` | | `defaultClick` | 是否默认点击跳转 | `boolean` | `true` | ### Events | 事件名 | 触发时机 | 参数 | | ------- | ---------------------------- | ------ | | `click` | defaultClick 为 false 时点击 | `href` | ### Slots | 名称 | 说明 | | ------- | ---------- | | default | 超链接内容 | ## 主题变量 | 变量名 | 说明 | | ----------------------- | -------------- | | `--snake-color-primary` | 超链接默认颜色 | # Loading 加载 用于按钮、图片和页面中的加载反馈,支持圆环、旋转条、跳动点和波浪四种形态。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue 正在提交 ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ------------------------- | ------------------------------------- | ----------------- | | `show` | 是否显示 | `boolean` | `true` | | `type` | 加载形态 | `circular \| spinner \| dots \| wave` | `circular` | | `color` | 图标颜色 | `string` | Snake 主色 | | `size` | 图标尺寸,数字按 rpx 处理 | `string \| number` | `34` | | `text` | 默认文字 | `string` | `''` | | `textColor` / `textSize` | 文字颜色与尺寸 | `string` / `string \| number` | 次要文字色 / `14` | | `direction` | 图标与文字排列方向 | `horizontal \| vertical` | `vertical` | | `inheritColor` | 是否继承父级颜色 | `boolean` | `false` | | `duration` | 动画周期,单位 ms | `number` | `800` | | `customClass` / `customStyle` | 根节点类名与样式 | `string` / `StyleValue` | `''` | ### Slots | 名称 | 说明 | | --------- | ------------------------------- | | `default` | 自定义加载文字,优先于 `text`。 | ## 主题变量 | 变量 | 用途 | | -------------------------- | ------------ | | `--snake-color-primary` | 默认图标颜色 | | `--snake-color-text-muted` | 默认文字颜色 | # Loadmore 加载更多 用于列表底部反馈分页状态。组件不直接请求数据,点击可加载状态时会派发 `loadmore`,由业务更新 `status`。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 动画与结束线 ```vue ``` `loadText` 可传字符串,也可传 `{ loadmore, loading, nomore }` 一次配置全部状态文案。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | -------------------------------- | -------------------------- | --------------------------- | ------------- | | `status` | loadmore/loading/nomore | `string` | `loadmore` | | `loadText` | 待加载文案或三态文案对象 | `string \| object` | `加载更多` | | `loadingText` | 加载中文案 | `string` | `正在加载...` | | `nomoreText` | 无更多文案 | `string` | `没有更多了` | | `icon` | 加载中是否显示动画 | `boolean` | `true` | | `iconType` | circle/flower/spinner | `string` | `circle` | | `iconColor` | 动画颜色 | `string` | 主题色 | | `isDot` | 无更多状态是否显示点状分隔 | `boolean` | `false` | | `color` / `fontSize` / `bgColor` | 文字颜色、字号和背景 | `string \| number` | 主题默认值 | | `marginTop` / `marginBottom` | 上下外边距 | `string \| number` | `0` | | `height` | 组件高度,数值按 rpx 处理 | `string \| number` | `auto` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ---------- | ------------------ | ------------- | | `loadmore` | 点击 loadmore 状态 | - | | `click` | 点击组件 | 当前 `status` | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | ---------------- | | `--snake-color-text-light` | 加载图标默认颜色 | | `--snake-color-text-secondary` | 状态文字默认颜色 | # Navbar 导航栏 用于页面顶部导航,支持状态栏安全区、返回操作、固定定位、标题及左右插槽。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 自定义右侧操作: ```vue ``` ## 固定导航栏的内容偏移 `fixed` 默认开启,页面正文需为导航栏预留顶部空间;`immersive` 仅适用于内容可延伸到状态栏背景的页面。需要拦截返回时使用 `custom-back`,否则组件调用默认返回逻辑。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------------------------- | -------------------------- | --------------------------- | -------------------------------- | | `title` | 中间标题 | `string` | `''` | | `height` | 导航内容高度,单位 px | `string \| number` | `44` | | `isBack` | 是否显示返回按钮 | `boolean` | `true` | | `backIconName` / `backIconColor` / `backIconSize` | 返回图标名称、颜色和尺寸 | 组合类型 | `arrow-left` / 主题文字色 / `40` | | `backText` / `backTextStyle` | 返回辅助文字及样式 | 组合类型 | `''` | | `titleWidth` / `titleColor` / `titleSize` / `titleBold` | 标题宽度、颜色、字号和字重 | 组合类型 | 主题默认值 | | `background` | 导航栏背景样式或颜色 | `string \| object \| array` | 白色表面背景 | | `fixed` / `immersive` | 固定顶部及是否允许内容沉浸 | `boolean` | `true` / `false` | | `safeAreaInsetTop` | 是否包含状态栏安全区 | `boolean` | `true` | | `borderBottom` | 是否显示底部分隔线 | `boolean` | `true` | | `zIndex` | 固定定位层级 | `string \| number` | `980` | | `customBack` | 自定义返回处理 | `() => void` | `null` | | `customClass` / `customStyle` | 自定义类名和样式 | 组合类型 | `''` | ### Slots | 插槽 | 说明 | | --------- | ---------------------- | | `left` | 返回区域后的左侧内容 | | `default` | 未设置标题时的中间内容 | | `right` | 右侧操作内容 | ### Events | 事件名 | 触发时机 | 参数 | | ------ | -------------- | ------- | | `back` | 点击返回区域时 | `event` | ## 主题变量 | 变量名 | 说明 | | ----------------------- | -------------------- | | `--snake-color-text` | 返回图标与标题默认色 | | `--snake-color-surface` | 导航栏默认背景色 | | `--snake-color-divider` | 底部分隔线颜色 | # NoNetwork 无网络提示 无网络提示组件。它自动监听网络状态:网络恢复时不渲染;断网时以固定定位的全屏遮罩提示用户,并提供重试入口。 适合放在页面根节点,用于订单、内容详情等网络不可用时无法继续操作的页面。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ::: warning 原生组件限制 普通的 fixed 遮罩无法覆盖 `video`、`map` 等原生组件。此类页面请由业务侧使用 `cover-view` 或对应平台的原生覆盖方案处理。 ::: ## 基础用法 ```vue ``` 组件在线时自动隐藏。断网时会全屏展示图片、提示语和重试按钮;点击重试后,组件会重新检测网络并触发 `retry` 事件。建议在事件回调中刷新当前页面的数据。 组件只负责网络状态与提示,不会自动重放失败请求;`retry` 中应由业务重新拉取当前页面所需数据。 ### 自定义提示语与图片 ```vue ``` `image` 可传入图片 URL 或 base64;未传入时使用内置断网插图。 ### 如何测试 1. 将组件放入需要保护的页面根节点。 2. 在真机上关闭 Wi-Fi 与移动数据,或在模拟器中切换为离线状态。 3. 返回页面查看全屏断网提示;恢复网络后提示会自动隐藏。 ::: tip 头条小程序不支持网络状态变化监听,因此不支持本组件。 ::: ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | -------- | --------------------------- | ------------------ | ------------ | | `tips` | 没有网络时的提示语 | `string` | 语言包默认值 | | `zIndex` | 组件层级值 | `number \| string` | `10080` | | `image` | 图片提示,图片地址或 base64 | `string` | 内置提示图 | ### Events | 事件名 | 触发时机 | 参数 | | ------- | ------------ | ---- | | `retry` | 点击重试按钮 | - | ### Methods | 方法名 | 说明 | | ------- | ----------------------------- | | `retry` | 重新检查网络并触发 retry 事件 | ## 主题变量 | 变量名 | 说明 | | -------------------------- | ------------------------ | | `--snake-color-surface` | 全屏提示背景色 | | `--snake-color-text-muted` | 提示文字、按钮边框和背景 | | `--snake-color-white` | 重试按钮文字颜色 | # 组件使用注意事项 这些约定适用于 Snake UI 的基础、表单和 CMS 组件。遵循它们可以减少组件无法解析、样式缺失和跨端表现不一致的问题。 ## 安装与编译 - npm 和 `uni_modules` 选择一种安装方式,不要同时维护两份组件库。 - 插件、样式和 easycom 路径必须来自同一种安装方式。 - `pages.json` 只能有一个 `easycom` 字段;新增规则时合并到已有的 `custom`。 - 修改 easycom、入口样式或插件注册后,重新编译项目。 - Snake UI 面向 uni-app Vue 3,不保证在普通 Vue Web 工程中直接运行。 ## 样式 - 在 `App.vue` 的非 scoped 样式中引入 `index.scss`。 - 页面需要使用 SCSS 语法时,为对应 ` ``` ## 检查结果 - 按钮能够正常渲染:easycom 路径正确。 - 按钮具有主题样式:`index.scss` 已生效。 - 点击后出现提示:`app.use(SnakeUI)` 已执行,`uni.$snake` 已注入。 - 控制台没有组件解析警告或样式编译错误。 ## 关于 uni.$snake 执行 `app.use(SnakeUI)` 后,常用工具会挂载到 `uni.$snake`,页面和组件内可以直接调用: ```ts uni.$snake.toast('操作成功'); uni.$snake.navTo('/pages/index/index'); ``` 挂载的工具包括 `toast`、`navTo`、`guid`、`sleep`、`formatTime` 和 `sys` 等。模块代码中也可以绕过全局属性,按需导入同名函数,行为一致: ```ts import { navTo, toast } from '@puresnake/snake-ui/libs'; toast('操作成功'); navTo('/pages/index/index'); ``` ## 不使用 easycom 单独引用组件 easycom 是推荐用法,但某些场景(如类型提示受限、动态组件)可以显式引入: ```vue ``` 显式引入时模板中的标签名必须与 import 的组件名一致。`uni_modules` 安装改用本地相对路径: ```ts import Button from './uni_modules/snake-ui/components/snake-button/snake-button.vue'; ``` ## 下一步 - 查找可用组件:[组件总览](/components/intro) - 配置主题、语言或 HTTP:[全局配置总览](/guide/foundation) - 使用装修组件:[CMS 快速接入](/cms/getting-started) - 接入异常:[常见问题](/guide/troubleshooting) # Radio 单选框 `RadioGroup` 与 `Radio` 成对使用:容器管理一组互斥的单选值、禁用状态、颜色与布局,`Radio` 通过 `name` 参与互斥选择。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue 鲜甜 香辣 清淡 ``` 布局通过 `width` 与 `wrap` 控制:`width` 指定每个 radio 的占宽(如 `width="240rpx"`),`wrap` 让每个 radio 单独占一行。 ## 初始值与禁用项 将组的 `v-model` 初始化为某个 `name` 即可预选。禁用单项不会影响其他选项;点击已选中的项不会清空选择,也不会再次触发 `change`。 ```vue 快递配送 到店自提 ``` ## API ### RadioGroup #### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ---------------------------- | ------------------ | ---------- | | `modelValue` | 当前选中的 name | `string \| number` | `''` | | `disabled` | 全组禁用 | `boolean` | `false` | | `activeColor` | 选中状态下的颜色 | `string` | 主题色 | | `size` | 整体尺寸 small/default/large | `string` | `''` | | `labelDisabled` | 是否禁止点击标签选中 | `boolean` | `false` | | `shape` | circle/square 形状 | `string` | `'circle'` | | `iconSize` | 勾号大小,单位 rpx | `UnitValue` | `''` | | `width` | 每个 radio 占组宽度 | `UnitValue` | `'auto'` | | `wrap` | 是否每个 radio 都换行 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | #### Events `update:modelValue` 和 `change` 均返回最新 name。 #### Slots 默认插槽放置 Radio。 ### Radio #### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ------------------------------------ | ------------------ | ------------ | | `label` | 展示标签文本 | `string` | `''` | | `name` | 数据项标识符 | `string \| number` | `''` | | `shape` | circle/square 形状 | `string` | 继承 Group | | `disabled` / `labelDisabled` | 禁用 / 禁止点击标签选中 | `boolean` | `false` | | `activeColor` | 选中颜色,设置后覆盖父级 activeColor | `string` | 主题色 | | `iconSize` / `labelSize` | 勾号与标签字号,单位 rpx | `UnitValue` | 按 size 预设 | | `size` | 整体尺寸 small/default/large | `string` | 继承 Group | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | #### Events `change(name)` — radio 从未选中变为选中时触发,携带当前 radio 的 name。点击已选中项不触发。 #### Slots 默认插槽用于标签内容。 ## 主题变量 | 变量 | 用途 | | --------------------------- | ---------------------- | | `--snake-color-primary` | 默认选中颜色 | | `--snake-color-border` | 未选中和禁用边框 | | `--snake-color-disabled-bg` | 禁用状态背景与图标颜色 | | `--snake-color-text` | 标签文字颜色 | `activeColor` 会覆盖当前实例或分组的默认主题色。 ## 类型定义 从包根导入 `RadioGroupProps`、`RadioProps` 与 `RadioEmits`。 # ReadMore 阅读更多 用于内容较长时预先收起一部分、点击展开全部内容的场景,超出占位高度才显示展开按钮。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 展开与收起 ```vue 长内容…… ``` `toggle` 为 true 时,展开后显示收起按钮;内容动态变化后可通过 `ref.init()` 重新测量高度。 异步富文本、图片加载完成或语言切换后都可能改变高度,应在内容更新后的 `nextTick` 调用 `init()`;不要用固定字符数代替高度测量。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ------------------------------ | --------------------------- | ------------------------- | | `showHeight` | 显示占位高度,数值按 rpx 处理 | `number \| string` | `400` | | `toggle` | 展开后是否显示收起按钮 | `boolean` | `false` | | `closeText` | 收起状态的提示文字 | `string` | 语言包默认值 | | `openText` | 展开状态的提示文字 | `string` | 语言包默认值 | | `color` | 提示文字颜色 | `string` | `--snake-color-primary` | | `fontSize` | 提示文字大小,数值按 rpx 处理 | `number \| string` | `28` | | `shadowStyle` | 收起时覆盖在内容底部的阴影样式 | `object \| array` | 渐隐到 surface 的默认阴影 | | `textIndent` | 段落首行缩进 | `string` | `2em` | | `index` | open/close 事件回调中的标识值 | `number \| string` | `''` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ------- | -------- | ------- | | `open` | 展开 | `index` | | `close` | 收起 | `index` | ### Methods | 方法名 | 说明 | | ------ | ------------------------------ | | `init` | 重新测量内容高度并刷新展开状态 | ### Slots | 插槽名 | 说明 | | --------- | ---------------- | | `default` | 需要折叠的长内容 | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | -------------------- | | `--snake-color-primary` | 展开和收起按钮颜色 | | `--snake-color-surface` | 收起状态渐隐终点颜色 | | `--snake-color-text-secondary` | 正文默认颜色 | # RootPortal 根节点传送 把插槽内容传送到页面根节点渲染,避免被祖先的 `transform`、`overflow` 或层叠上下文影响,主要用于解决复杂布局下 fixed 弹层失效、被裁剪的问题;也可用于在页面任意深度挂载 ``、`` 等全局服务组件。 :::tip 提示 组件会按平台自动选择实现:H5 使用 teleport,微信/支付宝小程序使用原生 `root-portal`,App 端使用 renderjs;其他平台不支持传送,内容原位渲染。仅在遇到层级或定位问题时使用。 ::: ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 用 `snake-root-portal` 包裹 fixed 定位的弹层,使其脱离带 `transform` 的父容器: ```vue 显示弹层 脱离 transform 容器的弹层 ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------- | ---------- | --------------------------- | ------ | | `customClass` | 自定义类名 | `string` | `''` | | `customStyle` | 根节点样式 | `string \| object \| array` | `''` | ### Slots | 插槽名 | 说明 | | --------- | ---------------- | | `default` | 需要传送的内容。 | ## 主题变量 传送后的内容脱离了 `snake-config-provider` 的作用范围,组件会在内层容器重新携带 `snake-theme-{mode}` 类名与主题 CSS 变量,弹层内的语义色与暗黑模式依然生效。 # Search 搜索框 搜索组件,集成了常见搜索框所需功能,支持圆形/方形、清除控件、右侧操作按钮与聚焦动画,一键引入开箱即用。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 形状与操作按钮 ```vue ``` `disabled` 为 true 时输入框不可编辑,点击组件会触发 `click`,通常用于跳转真正的搜索页。 ## 搜索提交与建议词 `search` 由键盘确认触发,`custom` 由右侧操作按钮触发;两者都携带当前关键字。输入联想应由业务在 `input` 中防抖请求,并在 `clear` 时清空建议列表。 ```vue ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ---------------------------------- | --------------------------- | ------------------------------ | | `shape` | 搜索框形状 | `round \| square` | `round` | | `bgColor` | 搜索框背景色 | `string` | `--snake-color-surface-muted` | | `placeholder` | 占位提示文字 | `string` | 语言包默认值 | | `clearabled` | 是否启用清除控件 | `boolean` | `true` | | `focus` | 是否自动聚焦 | `boolean` | `false` | | `showAction` | 是否在右侧显示操作按钮 | `boolean` | `true` | | `actionStyle` | 右侧操作按钮样式 | `object \| array` | `{}` | | `actionText` | 右侧操作按钮文字 | `string` | 语言包默认值 | | `inputAlign` | 输入框内容水平对齐方式 | `left \| center \| right` | `left` | | `disabled` | 是否禁用输入框 | `boolean` | `false` | | `animation` | showAction 时是否聚焦才展开 | `boolean` | `false` | | `borderColor` | 边框颜色,配置后才有边框 | `string` | `none` | | `modelValue` | 双向绑定的输入值 | `string` | `''` | | `height` | 搜索框高度,数值按 rpx 处理 | `number \| string` | `64` | | `inputStyle` | 输入框样式,对象形式 | `object \| array` | `{}` | | `maxlength` | 输入框最大长度,-1 不限制 | `number \| string` | `-1` | | `searchIconColor` | 搜索图标颜色,默认同输入框字体颜色 | `string` | `''` | | `color` | 输入框字体颜色 | `string` | `--snake-color-text-secondary` | | `placeholderColor` | placeholder 的颜色 | `string` | `--snake-color-text-muted` | | `margin` | 与上下左右元素的间距 | `string` | `0` | | `searchIcon` | 左侧图标名称或图片路径 | `string` | `search` | | `adjustPosition` | 弹出键盘时是否自动调节高度 | `boolean` | `true` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ------------------- | -------------------- | ------- | | `update:modelValue` | 输入值变化 | `value` | | `input` / `change` | 输入/内容变化 | `value` | | `search` | 用户确定搜索 | `value` | | `custom` | 点击右侧操作按钮 | `value` | | `clear` | 点击清除按钮 | - | | `focus` / `blur` | 输入框聚焦/失焦 | `value` | | `click` | 禁用状态下点击搜索框 | - | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | ---------------------- | | `--snake-color-surface-muted` | 搜索框默认背景色 | | `--snake-color-text-secondary` | 输入文字默认颜色 | | `--snake-color-text-muted` | 占位文字和操作按钮颜色 | | `--snake-color-text-light` | 清除图标颜色 | | `--snake-color-text` | 右侧操作按钮激活颜色 | # Select 列选择器 用于单列、多列、多列联动的选择场景,基于原生 picker-view 与 Popup 实现,底部弹出。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ```ts // 单列 const list = [ { label: '选项一', value: 'a' }, { label: '选项二', value: 'b' } ]; // 多列联动 const cascade = [{ label: '华东', value: 'east', children: [{ label: '上海', value: 'sh' }] }]; ``` ## 模式与回传 - `single-column` 单列;`mutil-column` 多列(list 为二维数组);`mutil-column-auto` 多列联动(按 `childName` 级联)。 - `confirm` / `cancel` 回调携带 `[{ value, label, extra? }]` 数组。 - `close` 在点击遮罩等非确认/取消方式关闭时触发。 - `preserveSelection` 为 true(默认)时,下次打开保留上次确认的选择。 ## 多列联动 联动模式使用树形数据;每一列变化后会根据 `child-name` 生成下一列。确认结果始终按列返回。 ```vue ``` ```ts const regions = [ { label: '华东', value: 'east', children: [ { label: '上海', value: 'sh' }, { label: '杭州', value: 'hz' } ] } ]; function onConfirm(values) { // values: [{ value: 'east', label: '华东' }, { value: 'sh', label: '上海' }] } ``` ## 受控打开与默认值 `v-model` 只控制弹层显示,选择结果由 `confirm`/`cancel` 接收。首次打开可用 `default-value` 指定各列下标;需要每次按默认值重置时设置 `:preserve-selection="false"`。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ------------------------------ | ---------------------------------------------------- | ------------------------------ | | `list` | 列数据 | `array` | `[]` | | `modelValue` | 双向绑定控制弹出与收起 | `boolean` | `false` | | `mode` | 模式选择 | `single-column \| mutil-column \| mutil-column-auto` | `single-column` | | `labelName` / `valueName` | 自定义 label/value 属性名 | `string` | `label` / `value` | | `childName` | 多列联动模式的 children 属性名 | `string` | `children` | | `defaultValue` | 默认选中的下标数组 | `number[]` | `[0]` | | `preserveSelection` | 是否保留上次确认的选择 | `boolean` | `true` | | `title` | 顶部标题 | `string` | `''` | | `cancelText` / `confirmText` | 取消/确认按钮文字 | `string` | 语言包默认值 | | `cancelColor` | 取消按钮颜色 | `string` | `--snake-color-text-secondary` | | `confirmColor` | 确认按钮颜色 | `string` | `--snake-color-primary` | | `zIndex` | 弹出层级,0 使用弹层默认层级 | `number \| string` | `0` | | `maskCloseAble` | 是否允许点击遮罩关闭 | `boolean` | `true` | | `safeAreaInsetBottom` | 是否开启底部安全区适配 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ------------------- | ------------------------ | ---------------------------- | | `update:modelValue` | 弹出/收起 | `boolean` | | `confirm` | 点击确认按钮 | `[{ value, label, extra? }]` | | `cancel` | 点击取消按钮 | `[{ value, label, extra? }]` | | `close` | 点击遮罩等非按钮方式关闭 | - | ## 主题变量 | 变量 | 用途 | | ------------------------------ | ---------------- | | `--snake-color-primary` | 默认确认按钮颜色 | | `--snake-color-text` | 当前选项文字颜色 | | `--snake-color-text-secondary` | 默认取消按钮颜色 | | `--snake-color-border` | 工具栏分隔线 | | `--snake-color-surface` | 选择器背景 | | `--snake-color-surface-rgb` | 滚轮遮罩渐变背景 | `confirmColor` 和 `cancelColor` 可以覆盖单个实例的操作颜色。 # 配置 完成安装后,需要注册 Snake UI、引入全局样式,并让 uni-app 自动发现 `` 组件。 ## 1. 注册组件库 ::: code-group ```ts [npm] import { createSSRApp } from 'vue'; import App from './App.vue'; import SnakeUI from '@puresnake/snake-ui'; export function createApp() { const app = createSSRApp(App); app.use(SnakeUI); return { app }; } ``` ```ts [uni_modules] import { createSSRApp } from 'vue'; import App from './App.vue'; import SnakeUI from './uni_modules/snake-ui'; export function createApp() { const app = createSSRApp(App); app.use(SnakeUI); return { app }; } ``` ::: 主题、国际化、HTTP 和 CMS 服务都可以通过第二个参数配置,完整选项见[全局配置总览](/guide/foundation)。 ## 2. 引入全局样式 在 `App.vue` 的全局样式中选择与安装方式匹配的路径: ::: code-group ```vue [npm] ``` ```vue [uni_modules] ``` ::: `index.scss` 包含组件基础样式、主题变量和[内置样式类](/components/common)。只需要 SCSS 主题变量时,可单独引入 `theme.scss`。 ## 3. 配置 easycom 在 `pages.json` 中配置一条规则: ::: code-group ```json [npm] { "easycom": { "autoscan": true, "custom": { "^snake-(.*)": "@puresnake/snake-ui/components/snake-$1/snake-$1.vue" } } } ``` ```json [uni_modules] { "easycom": { "autoscan": true, "custom": { "^snake-(.*)": "@/uni_modules/snake-ui/components/snake-$1/snake-$1.vue" } } } ``` ::: 项目中只能有一个 `easycom` 字段;已有配置时应合并 `custom` 规则。修改后请重新编译项目。 ## 4. 使用组件 配置完成后无需在页面中注册: ```vue ``` 如果不使用 easycom,也可以按组件路径手动导入: ```ts import Button from '@puresnake/snake-ui/components/snake-button/snake-button.vue'; import Popup from '@puresnake/snake-ui/components/snake-popup/snake-popup.vue'; ``` 接下来用[快速上手](/components/quickstart)检查组件和全局工具是否都已生效。 # Skeleton 骨架屏 `Skeleton` 在首次请求尚未完成时预显示页面结构,支持快速段落模式和自定义骨架模板;`SkeletonItem` 是可组合的基础占位块,用于自由搭建骨架结构。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 快速模式通过 `avatar`、`title` 和 `rows` 等属性直接生成默认骨架: ```vue 真实内容 ``` ## 自定义模板 在 `template` 插槽中用 `SkeletonItem` 自由组合业务骨架: ```vue 真实内容 ``` `SkeletonItem` 支持 `text`、`rect`、`circle`、`image` 四种占位形态,也可以脱离 `Skeleton` 独立使用。 ## 与请求状态配合 仅在首次加载使用骨架屏;已有内容刷新时保留旧内容并用局部 loading 反馈,避免整页反复闪烁。 ```vue ``` ## API ### Skeleton #### Props | 参数 | 说明 | 类型 | 默认值 | | ------------- | ------------------------ | --------------------------- | -------- | | `loading` | 是否显示骨架 | `boolean` | `true` | | `animated` | 是否启用流光动画 | `boolean` | `true` | | `title` | 是否显示默认标题占位 | `boolean` | `true` | | `titleWidth` | 默认标题宽度 | `string \| number` | `40%` | | `titleHeight` | 默认标题高度 | `string \| number` | `18` | | `rows` | 默认段落行数 | `number` | `3` | | `rowsWidth` | 默认段落宽度,可逐行配置 | `string \| number \| Array` | `100%` | | `rowsHeight` | 默认段落高度,可逐行配置 | `string \| number \| Array` | `16` | | `avatar` | 是否显示默认头像占位 | `boolean` | `false` | | `avatarSize` | 默认头像尺寸 | `string \| number` | `32` | | `avatarShape` | 默认头像形状 | `circle \| square` | `circle` | | `customStyle` | 根节点样式 | `string \| object \| array` | `''` | #### Slots | 名称 | 说明 | | ---------- | -------------------- | | `default` | 加载完成后的真实内容 | | `template` | 自定义骨架模板 | ### SkeletonItem #### Props | 参数 | 说明 | 类型 | 默认值 | | ------------- | ------------------------------------- | --------------------------------- | ------ | | `variant` | 占位形态 | `text \| rect \| circle \| image` | `text` | | `width` | 宽度,裸数字按 rpx;默认值显式使用 px | `string \| number` | 按形态 | | `height` | 高度,裸数字按 rpx;默认值显式使用 px | `string \| number` | 按形态 | | `radius` | 圆角,裸数字按 rpx;默认值显式使用 px | `string \| number` | 按形态 | | `animated` | 动画开关,默认继承骨架容器 | `boolean` | `true` | | `customStyle` | 根节点样式 | `string \| object \| array` | `''` | ## 主题变量 | 变量 | 用途 | | ---------------------------- | -------------- | | `--snake-skeleton-color` | 骨架基础背景色 | | `--snake-skeleton-highlight` | 流光高亮颜色 | # Slider 滑动选择器 通过轨道点击或触摸拖动选择数值,支持步长、数值气泡、边界值与自定义滑块。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ```vue ``` H5 中轨道可通过 Tab 聚焦,方向键按照 `step` 调整数值;触摸拖动、轨道点击和键盘调整都会遵守 `min`、`max` 与步长归一化规则。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ---------------------------------------------- | -------------------------- | ------------------- | ----------------------- | | `modelValue` / `min` / `max` / `step` | 当前值、范围和步长 | `number \| string` | `0` / `0` / `100` / `1` | | `height` / `blockWidth` | 轨道高度和滑块尺寸 | `UnitValue` | `6` / `30` | | `activeColor` / `inactiveColor` / `blockColor` | 状态颜色 | `string` | 主题默认值 | | `blockStyle` | 滑块附加样式 | `style` | `''` | | `disabled` / `useSlot` | 禁用和使用自定义滑块 | `boolean` | `false` | | `showValue` / `valuePosition` | 数值气泡和 top/bottom 位置 | `boolean \| string` | `false` / `top` | | `showEdgeValue` | 显示最小和最大值 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | ### Events | 事件名 | 说明 | 参数 | | -------------------------- | -------------------- | ----- | | `update:modelValue` | 拖动或点击实时更新 | value | | `start` / `moving` / `end` | 触摸开始、移动、结束 | value | | `change` | 点击或拖动结束 | value | ### Expose | 方法 | 说明 | | ---------- | ------------------------------ | | `update()` | 容器尺寸变化后重新测量轨道位置 | ### Slots | 插槽名 | 说明 | 参数 | | --------- | ---------------------------- | ----------- | | `default` | `useSlot` 开启时替换默认滑块 | `{ value }` | ## 主题变量 | 变量名 | 说明 | | -------------------------- | -------------- | | `--snake-color-primary` | 激活轨道默认色 | | `--snake-color-divider` | 未激活轨道颜色 | | `--snake-color-text-muted` | 边界值文字颜色 | # Sticky 吸顶 通过节点测量和页面滚动状态实现跨端吸顶,不再只依赖浏览器 CSS sticky。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue 筛选导航 ``` ## 导航栏偏移与动态内容 固定导航栏下使用 `offset-top` 避开导航区。异步筛选项、图片或折叠内容改变高度后,等待视图更新并调用实例 `update()` 重新测量。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | ---------------------------------------- | ------------------ | ------------------ | | `offsetTop` | 吸顶偏移,裸数字按 rpx,显式 px 原样使用 | `string \| number` | `0` | | `customNavHeight` | 自定义导航栏高度 | `string \| number` | `0` | | `scrollTop` | 外部滚动位置;也会监听页面滚动 | `number` | `0` | | `zIndex` / `bgColor` | 层级和背景 | `number / string` | `10 / transparent` | | `disabled` | 禁用吸顶 | `boolean` | `false` | | `index` | 事件携带的业务索引 | `string \| number` | `0` | | `customClass` / `customStyle` | 自定义类名和样式 | 多类型 | `''` | ### Events | 事件名 | 触发时机 | 参数 | | --------- | ---------------- | -------------------- | | `fixed` | 进入固定状态 | `{ isFixed, index }` | | `unfixed` | 离开固定状态 | `{ isFixed, index }` | | `change` | 固定状态发生变化 | `{ isFixed, index }` | ### Slots | 插槽名 | 说明 | | --------- | -------- | | `default` | 吸顶内容 | ### Expose | 方法 | 说明 | | ---------- | ------------------------------ | | `update()` | 内容尺寸改变后异步重新测量位置 | ## 主题变量 组件未直接使用 CSS 主题变量。可通过 `bgColor` 设置背景,并通过 `customStyle` 覆盖其他视觉样式。 # Subsection 分段选择器 用于在少量互斥选项之间快速切换,支持按钮式滑块和描边分段两种模式。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 对象选项可通过 `disabled: true` 禁止切换: ```vue ``` H5 中当前分段可通过 Tab 聚焦,左右方向键会循环切换,并自动跳过禁用选项。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | ------------------------ | ------------------------------------------------------- | --------------- | | `list` | 字符串或对象选项列表 | `Array` | `[]` | | `current` | 当前选中索引 | `number \| string` | `0` | | `mode` | 按钮滑块或描边分段模式 | `button \| subsection` | `button` | | `activeColor` / `inactiveColor` | 激活和未激活文字颜色 | `string` | 主题默认值 | | `fontSize` / `height` | 字号与组件高度 | `string \| number` | `28` / `70` | | `animation` / `bold` | 滑块动画与激活项加粗 | `boolean` | `true` / `true` | | `bgColor` / `buttonColor` | 按钮模式的轨道和滑块颜色 | `string` | 主题默认值 | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ---------------- | ---------------- | ------- | | `change` | 选中新的可用选项 | `index` | | `update:current` | 选中索引更新 | `index` | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | ------------------------ | | `--snake-color-primary` | 激活文字及描边颜色 | | `--snake-color-text-secondary` | 未激活文字颜色 | | `--snake-color-surface-muted` | 按钮模式轨道背景色 | | `--snake-color-surface` | 描边模式背景色 | | `--snake-color-white` | 按钮模式激活文字默认颜色 | # Swiper 轮播图 基于 uni-app swiper 封装,支持图片或对象数据、自定义指示器、标题和 3D 卡片效果。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 指示器与 3D 卡片 ```vue ``` 对象图片依次读取 `name` 指定字段、`src`、`url`;标题读取 `title` 或 `text`。 ```ts const banners = [ { id: 'new', image: '/static/banner-new.png', title: '新品上市' }, { id: 'sale', image: '/static/banner-sale.png', title: '限时活动' } ]; ``` ## 受控切换与自定义指示器 将 `current` 绑定到状态可由业务主动切换轮播项;`change` 返回的新索引应同步回状态。`indicator` 插槽携带 `current` 与 `total`。 ```vue ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------------------- | -------------------------------------------------------------- | --------------------------- | -------------------------------- | | `list` | 图片地址或对象列表 | `Array` | `[]` | | `current` / `height` | 当前索引、轮播高度 | `number \| string` | `0` / `250` | | `autoplay` / `interval` / `duration` / `circular` | 自动播放、间隔、动画时长、循环 | `boolean \| number` | `true` / `3000` / `300` / `true` | | `indicator` | 是否显示自定义指示器;也兼容配置对象 | `boolean \| object` | `{}` | | `mode` | round/dot/rect/line/number | `string` | `round` | | `indicatorPos` | topLeft/topCenter/topRight/bottomLeft/bottomCenter/bottomRight | `string` | `bottomCenter` | | `indicatorColor` / `indicatorActiveColor` | 普通和激活指示器颜色 | `string` | 半透明白 / 白色 | | `name` | 对象图片字段 | `string` | `image` | | `radius` / `borderRadius` | 圆角,borderRadius 优先 | `string \| number` | `8` | | `previousMargin` / `nextMargin` | 前后边距 | `string` | `0px` | | `effect3d` / `effect3dPreviousMargin` | 3D 卡片及露出边距 | `boolean \| UnitValue` | `false` / `50` | | `imgMode` | 图片裁剪模式 | `string` | `aspectFill` | | `showTitle` / `title` / `titleStyle` | 标题显示、兼容别名和样式 | `boolean \| style` | `false` | | `bgColor` / `customClass` / `customStyle` | 背景与自定义样式 | `string \| object \| array` | 主题默认值 | ### Events | 事件名 | 触发时机 | 参数 | | ----------------- | ---------- | ---------------------- | | `change` | 当前项变化 | `current: number` | | `animationfinish` | 动画结束 | `{ current, source? }` | | `click` | 点击轮播项 | `index: number` | ### Slots | 插槽名 | 说明 | | ----------- | ------------------------------------------- | | `indicator` | 替换内置指示器,参数为 `{ current, total }` | ## 主题变量 组件未直接使用 CSS 主题变量。可通过 `indicatorColor`、`indicatorActiveColor`、`bgColor` 和 `customStyle` 调整视觉样式。 # Switch 开关 切换 boolean、字符串或数字状态,支持加载、禁用、自定义值和短震动反馈。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` H5 中组件可通过 Tab 聚焦,并使用 Enter 或空格切换。`disabled` 或 `loading` 时会退出键盘焦点顺序,也不会更新绑定值。 ## 异步切换 切换远程设置时,用 `loading` 锁定当前开关;请求失败后将绑定值恢复为原值,避免界面与服务端状态不一致。 ```vue ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | ---------------- | ----------------------------- | ---------------- | | `modelValue` | 当前值 | `boolean \| string \| number` | `false` | | `activeValue` / `inactiveValue` | 开启和关闭值 | 同 modelValue | `true` / `false` | | `loading` / `disabled` | 加载和禁用 | `boolean` | `false` | | `size` / `space` | 开关尺寸和内边距 | `UnitValue` | `50` / `2` | | `activeColor` / `inactiveColor` | 开启和关闭颜色 | `string` | 主题默认值 | | `vibrateShort` | 切换时尝试短震动 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | ### Events | 事件名 | 说明 | 参数 | | ------------------------------ | ------------------------ | ----- | | `update:modelValue` / `change` | 状态更新 | 新值 | | `click` | 点击组件,禁用时也会触发 | event | ## 主题变量 | 变量 | 用途 | | ----------------------- | ------------------ | | `--snake-color-primary` | 默认开启颜色与焦点 | | `--snake-color-border` | 默认关闭颜色 | `activeColor` 和 `inactiveColor` 可以覆盖单个实例的对应颜色。 # Tabbar 底部导航栏 用于页面底部的一级导航。支持选中态图标、角标、安全区、固定定位和中间凸起按钮。 ## 使用建议 Tabbar 只用于应用的一级目的地,项目应保持固定的项目数量与顺序。临时操作、筛选或页面内切换分别使用 Button、DropMenu 或 Tabs。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 通过 `v-model` 按索引维护选中项: ```vue ``` 为中间项设置 `mid-button`,并在对应项中设置 `midButton: true`,即可显示凸起按钮: ```vue { key: 'publish', text: '发布', iconPath: 'plus', midButton: true } ``` ## 无障碍 - 每一项都提供简短且唯一的文字标签,不能只显示图标。 - 当前项除颜色外还应保持选中状态语义;角标数量变化需要有对应的业务提示。 - 中间凸起按钮若代表“发布”等操作,应使用动作文案,不要伪装成导航目的地。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | ------------------------------------------------------ | ------------------------------- | ----------------- | | `items` / `list` | 导航项列表;优先使用 `items` | `TabbarItem[]` | `[]` | | `current` | 当前激活项的 `key` | `string \| number` | `''` | | `modelValue` | 通过 `v-model` 绑定的激活项索引 | `string \| number` | `0` | | `show` / `fixed` | 显示导航栏、固定在页面底部 | `boolean` | `true` / `true` | | `safeAreaInsetBottom` | 是否预留底部安全区 | `boolean` | `true` | | `activeColor` / `inactiveColor` | 激活和未激活颜色 | `string` | 主色 / 弱化文字色 | | `bgColor` | 背景色 | `string` | 表面背景色 | | `borderTop` | 是否显示顶部边框 | `boolean` | `true` | | `hideTabBar` | 挂载时隐藏原生 tabBar;非原生 tabBar 页安全忽略 | `boolean` | `true` | | `beforeSwitch` | 切换拦截器;返回 `true` 或 resolve 的 Promise 才会切换 | `(index) => boolean \| Promise` | - | | `midButton` | 是否启用中间凸起按钮 | `boolean` | `false` | | `iconSize` / `midButtonSize` | 常规图标和凸起图标尺寸,数字单位为 rpx | `string \| number` | `40` / `100` | | `textSize` / `gap` | 文字尺寸、图标与文字间距,数字单位为 rpx | `string \| number` | `22` / `5` | | `height` | 导航栏高度,数字单位为 rpx | `string \| number` | `104` | | `zIndex` | 固定导航栏层级 | `number` | `120` | | `customClass` / `customStyle` | 根节点类名和样式 | `string` / `StyleValue` | `''` / `''` | ## 原生 tabBar 将 `snake-tabbar` 放在 `pages.json` 的原生 tabBar 页面时,组件默认调用 `uni.hideTabBar()`,由自定义栏替代原生栏。普通页面也可以复用组件:该 API 的预期失败会被内部安全处理。传入 `:hide-tab-bar="false"` 可保留原生 tabBar。 ### TabbarItem | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | ---------------------------------------- | ------------------- | ------------ | | `key` | 导航项唯一标识 | `string \| number` | 当前索引 | | `text` | 导航文字 | `string` | `''` | | `icon` / `iconPath` | 未选中图标名称,`iconPath` 优先 | `string` | `''` | | `selectedIconPath` | 选中图标名称 | `string` | 未选中图标 | | `customIcon` | 图标字体前缀;传字符串时直接作为前缀 | `boolean \| string` | `false` | | `pagePath` | 页面路径;传入后按当前页面自动确定激活项 | `string` | `''` | | `midButton` | 是否作为中间凸起项 | `boolean` | `false` | | `width` | 单项宽度;任一项设置后其余项填充剩余空间 | `string \| number` | 自动均分 | | `iconSize` / `textSize` / `gap` | 单项图标尺寸、文字尺寸、间距 | `string \| number` | 继承组件属性 | | `badge` / `count` | 角标文字或数量,`badge` 优先 | `string \| number` | `undefined` | | `isDot` | 是否仅显示点状角标 | `boolean` | `false` | | `disabled` | 是否禁用点击 | `boolean` | `false` | ### Events | 事件名 | 触发时机 | 参数 | | ------------------- | ---------------------------- | ----------- | | `change` | 点击未禁用的导航项 | `key, item` | | `update:modelValue` | 点击无 `pagePath` 的导航项时 | `index` | `pagePath` 存在时,组件会调用 `uni.switchTab()`;不需要由父组件重复处理跳转。`beforeSwitch` 返回 `false` 或 rejected Promise 时,组件不发出事件、不更新值、也不跳转。 ## 主题变量 | 变量名 | 说明 | | ----------------------------- | ------------------------ | | `--snake-color-primary` | 默认激活颜色 | | `--snake-color-text-muted` | 默认未激活颜色 | | `--snake-color-surface` | 导航栏和中间按钮背景色 | | `--snake-color-surface-muted` | 按压背景色 | | `--snake-color-divider` | 顶部边框和中间按钮描边色 | | `--snake-color-error` | 角标背景色 | # Tabs 标签页 用于同层级内容切换:滚动模式下激活标签自动居中,非滚动模式下标签均分宽度,所有标签保持单行。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 `current` 由父级控制,点击其他标签时 `change` 返回新索引: ```vue ``` ## 均分标签 默认 `isScroll=true`,标签可左右拖动。少量标签可关闭滚动并均分容器宽度: ```vue ``` ## 徽标和隐藏项 ```vue ``` `name` 和 `count` 可指定对象中的字段名;`isDot` 可将数字徽标改成圆点。`hidden` 隐藏标签但不改变其原数组索引。 ## 动态数据 异步更新 `list` 后,等待视图更新再调用实例的 `init()`,重新测量标签宽度与滑块位置;如果当前索引已超出新列表范围,应由业务先重置 `current`。 ```ts tabs.value = await getTabs(); current.value = Math.min(current.value, Math.max(tabs.value.length - 1, 0)); await nextTick(); tabsRef.value?.init(); ``` ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------- | -------------------------------- | ------------------ | ------------------------- | | `list` | 标签对象数组 | `TabItem[]` | `[]` | | `current` | 当前激活索引 | `number \| string` | `0` | | `isScroll` | 是否允许横向拖动 | `boolean` | `true` | | `height` / `fontSize` | 高度和字号,数值单位 rpx | `number \| string` | `80` / `30` | | `duration` | 动画时长,单位秒 | `number \| string` | `0.5` | | `activeColor` / `inactiveColor` | 激活与未激活文字颜色 | `string` | 主题色 / 主文字色 | | `barWidth` / `barHeight` | 滑块宽高,数值单位 rpx | `number \| string` | `40` / `6` | | `gutter` | 滚动模式单侧内边距,数值单位 rpx | `number \| string` | `30` | | `bgColor` | 背景色 | `string` | `#fff` | | `name` / `count` | 标题与徽标字段名 | `string` | `name` / `count` | | `offset` | 徽标 `[top, right]` 偏移 | `[number, number]` | `[5, 20]` | | `isDot` / `bold` / `showBar` | 圆点徽标、激活加粗、显示滑块 | `boolean` | `false` / `true` / `true` | | `activeItemStyle` / `barStyle` | 激活项和滑块附加样式 | `object` | `{}` | | `itemWidth` | 标签宽度 | `number \| string` | `auto` | | `customClass` / `customStyle` | 根节点自定义类和样式 | `string` / 样式值 | 空 | ### Events | 事件名 | 触发时机 | 参数 | | -------- | -------------- | ------- | | `change` | 点击非当前标签 | `index` | ### Methods | 方法 | 说明 | | ----------------- | -------------------------------- | | `init()` | 重新测量标签布局 | | `clickTab(index)` | 执行与点击标签一致的逻辑 | | `scrollByIndex()` | 按当前激活索引更新滚动位置和滑块 | ## 主题变量 | 变量名 | 说明 | | ----------------------- | ------------------ | | `--snake-color-primary` | 激活文字和滑块颜色 | | `--snake-color-text` | 未激活文字颜色 | | `--snake-color-error` | 徽标默认背景色 | # Text 文本 集成了文本类在项目中的常用功能:价格、手机号/姓名脱敏、日期格式化、超链接与拨打电话,几乎涵盖大部分文本场景。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 模式与格式化 ```vue ``` 脱敏和日期格式化仅用于展示,不会修改原始值;需要提交或计算时仍应使用业务数据源。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------------- | -------------------------------- | ------------------------------------------------------------------------------------ | -------------------- | | `type` | 主题颜色 | `primary \| warning \| success \| info \| error \| main \| content \| tips \| light` | `''` | | `show` | 是否显示文本 | `boolean` | `true` | | `text` | 显示的值 | `string \| number` | `''` | | `prefixIcon` / `suffixIcon` | 前置/后置图标 | `string` | `''` | | `mode` | 文本处理模式 | `text \| price \| phone \| name \| date \| link` | `text` | | `href` | mode 为 link 时的链接地址 | `string` | `''` | | `format` | 格式化规则,encrypt 或函数 | `string \| function` | `''` | | `call` | mode 为 phone 时点击是否拨打电话 | `boolean` | `false` | | `openType` | 小程序打开方式 | `string` | `''` | | `bold` | 是否粗体 | `boolean` | `false` | | `block` | 是否块状显示 | `boolean` | `false` | | `lines` | 显示行数,超出显示省略号 | `string \| number` | `''` | | `color` | 文本颜色 | `string` | `--snake-color-text` | | `size` | 字体大小 | `string \| number` | `28` | | `iconStyle` / `textStyle` | 图标/文字样式 | `object \| array \| string` | 默认图标样式 / `{}` | | `decoration` | 文字装饰 | `none \| underline \| line-through` | `none` | | `margin` | 外边距 | `object \| string \| number` | `0` | | `lineHeight` | 行高 | `string \| number` | `''` | | `align` | 对齐方式 | `left \| center \| right` | `left` | | `wordWrap` | 换行方式 | `break-word \| normal \| anywhere` | `normal` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ------------------------------------------------------------------------------------ | --------------------- | -------------- | | `click` | 点击文本 | - | | `getuserinfo` / `contact` / `getphonenumber` / `error` / `launchapp` / `opensetting` | openType 对应原生事件 | `event.detail` | ### Slots | 名称 | 说明 | | ------- | ---------------- | | default | 替换默认显示内容 | ## 主题变量 | 变量名 | 说明 | | ------------------------------ | -------------------- | | `--snake-color-text` | 默认文字及 main 颜色 | | `--snake-color-text-secondary` | content 及图标颜色 | | `--snake-color-text-muted` | tips 颜色 | | `--snake-color-text-light` | light 颜色 | | `--snake-color-primary` | primary 颜色 | | `--snake-color-success` | success 颜色 | | `--snake-color-warning` | warning 颜色 | | `--snake-color-error` | error 颜色 | | `--snake-color-info` | info 颜色 | # Textarea 文本域 用于多行文本输入,支持固定或自适应高度、字数统计和 Form 校验联动。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 中文、日文等输入法处于候选组合阶段时,组件只更新内部显示;组合结束后才同步 `v-model` 并触发表单 `change` 校验,避免半成品拼音造成误校验。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------------------------ | ---------------------- | ---------------------- | --------------------------- | | `modelValue` / `placeholder` / `maxlength` | 值、占位和最大长度 | `string \| number` | `''` / `请输入内容` / `140` | | `height` / `autoHeight` / `fixed` | 高度、自适应和固定区域 | `UnitValue \| boolean` | `120` / `false` | | `count` | 显示字数统计 | `boolean` | `false` | | `disabled` / `readonly` | 禁用和只读 | `boolean` | `false` | | `border` / `size` / `fontSize` | 边框、尺寸和字号 | `string \| UnitValue` | `surround` | | `focus` / `cursor` / `selectionStart` / `selectionEnd` | 焦点和光标 | `boolean \| number` | 原生默认值 | | `confirmType` / `confirmHold` / `showConfirmBar` | 键盘确认栏 | `string \| boolean` | `return` / `false` / `true` | | `adjustPosition` / `holdKeyboard` / `cursorSpacing` | 键盘行为 | `boolean \| number` | 原生默认值 | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | ### Events | 事件名 | 说明 | 参数 | | ---------------------------------------- | ---------------------- | ---------------- | | `update:modelValue` / `input` / `change` | 值更新、输入和失焦确认 | `value` | | `focus` / `blur` / `linechange` | 焦点和行数变化 | 原生事件 | | `confirm` | 键盘确认 | `(value, event)` | | `keyboardheightchange` | 键盘高度变化 | 原生事件 | ## 主题变量 | 变量名 | 说明 | | --------------------------- | ---------------- | | `--snake-color-text` | 输入文字颜色 | | `--snake-color-text-light` | 占位文字颜色 | | `--snake-color-text-muted` | 字数统计颜色 | | `--snake-color-divider` | 默认边框颜色 | | `--snake-color-primary` | 聚焦边框颜色 | | `--snake-color-error` | 校验失败边框颜色 | | `--snake-color-disabled-bg` | 禁用状态背景色 | | `--snake-radius-md` | 容器圆角 | # Tooltip 文字提示 Tooltip 用于展示与触发元素相关的简短说明或非操作性内容。它以默认插槽作为触发元素,内容可通过 `content` 属性或 `content` 插槽传入。 Snake Tooltip 与 Wot UI Tooltip 的用途相同,但定位和关闭机制并不相同:Snake 用 CSS 将浮层附着在触发元素上,并用透明遮罩处理点击外部关闭;Wot UI 会测量浮层位置,点击外部关闭通常由页面配合 `useQueue()` 处理。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` ## 富内容与受控显示 `content` 插槽可承载 `snake-parse` 等内容组件;使用 `v-model` 可由页面主动控制显隐。 ```vue ``` ## 方向 支持 `top`、`bottom`、`left`、`right` 及各自的 `-start`、`-end` 变体,共 12 种,默认是 `bottom`。箭头会按触发元素与浮层的实际尺寸对齐。打开一个 Tooltip 时,其余已打开的 Tooltip 会自动关闭;点击透明区域默认关闭当前 Tooltip。 内容应保持简短且不可承载关键操作;复杂交互请使用 Popup。受控模式下由 `v-model` 统一维护显隐,避免同时调用实例方法和修改绑定值。 浮层不会自动翻转方向,也不能越过父级的 `overflow: hidden` 裁剪。靠近屏幕边缘或位于裁剪容器内时,应选择合适的 `placement`,或将触发元素放在不裁剪浮层的容器中。 ## 动态内容与位置刷新 内容插槽会随 Vue 状态重新渲染,浮层的 CSS 位置会跟随内容尺寸变化。若插槽的宽高在打开后发生变化,可在 DOM 更新后调用 `updatePosition()`,重新测量箭头位置。 ```vue ``` ## 与 Wot UI 的 API 差异 | 功能 | Snake Tooltip | Wot UI Tooltip | | ------------ | ------------------------------------------------------- | -------------------------------------------------- | | 关闭按钮 | `closeable`,也接受 `show-close` | `show-close` | | 内容插槽 | 直接使用 `#content` | 当前源码也会自动识别 `#content` | | 点击外部关闭 | 内置透明遮罩,默认关闭,可用 `closeOnClickOverlay` 控制 | 页面使用 `useQueue().closeOutside()` | | `offset` | 浮层与触发元素的间距;数字按 `rpx` 处理 | 沿坐标轴调整位置,接受数字、数组或对象,按像素处理 | | 内容尺寸变化 | 浮层由 CSS 重新布局,`updatePosition()` 刷新箭头对齐 | `updatePosition()` 重新测量并定位浮层 | | 显隐动画 | 立即显示和关闭 | 200ms 淡入淡出 | `customArrow` 和 `customPop` 分别用于箭头与浮层面板的类名;`contentClass`、`contentStyle` 只作用于内容容器。Wot UI 文档示例仍写有 `use-content-slot`,但当前 Tooltip 类型与组件实现均没有这个属性。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | --------------------- | ------------------------------------- | ------------------ | ---------- | | `v-model` | 是否显示 | `boolean` | `false` | | `content` | 纯文本内容;有 `content` 插槽时不使用 | `string` | `''` | | `placement` | 展示方向 | `TooltipPlacement` | `'bottom'` | | `offset` | 与触发元素间距,数值按 `rpx` 处理 | `number \| string` | `8` | | `visibleArrow` | 是否显示箭头 | `boolean` | `true` | | `disabled` | 是否禁用触发 | `boolean` | `false` | | `closeable` | 是否显示关闭按钮 | `boolean` | `false` | | `showClose` | 关闭按钮兼容别名 | `boolean` | `false` | | `closeOnClickOverlay` | 点击透明区域是否关闭 | `boolean` | `true` | | `zIndex` | 透明遮罩层级 | `number` | `10070` | | `customClass` | 根节点自定义类名 | `string` | `''` | | `customStyle` | 根节点自定义样式 | `StyleValue` | `''` | | `customArrow` | 箭头自定义类名 | `string` | `''` | | `customPop` | 浮层面板自定义类名 | `string` | `''` | | `contentClass` | 内容容器自定义类名 | `string` | `''` | | `contentStyle` | 内容容器自定义样式 | `StyleValue` | `''` | ### Events | 事件名 | 说明 | 回调参数 | | --------------- | ------------------ | ------------------- | | `change` | 显隐状态变化 | `{ show: boolean }` | | `open` | 打开后触发 | - | | `close` | 关闭后触发 | - | | `click-overlay` | 点击透明区域时触发 | `event` | ### Methods 通过组件 ref 可调用以下方法: | 方法名 | 说明 | | ------------------ | ------------------ | | `open()` | 打开 Tooltip | | `close()` | 关闭 Tooltip | | `toggle()` | 切换显示状态 | | `updatePosition()` | 重新测量并对齐箭头 | ### Slots | 插槽名 | 说明 | | --------- | --------------------------------------- | | `default` | 触发 Tooltip 的元素 | | `content` | Tooltip 内容;优先级高于 `content` 属性 | ## 主题变量 | 变量名 | 说明 | | ---------------------------- | ---------- | | `--snake-tooltip-color` | 文字颜色 | | `--snake-tooltip-background` | 背景色 | | `--snake-tooltip-radius` | 圆角 | | `--snake-tooltip-shadow` | 阴影 | | `--snake-tooltip-padding` | 内容内边距 | | `--snake-tooltip-font-size` | 字号 | # Transition 过渡动画 跨端内容进出场动画,Overlay 和 Popup 均使用该组件。离场完成前节点会继续保留,因此不会出现弹层瞬间消失的问题。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue 内容 ``` 动画名支持 `fade`、`fade-up/down/left/right`、`slide-up/down/left/right`、`zoom-in` 和 `zoom-out`。 ## 分别设置进出场 `duration` 可传对象,为进入和离开设置不同节奏;通过生命周期事件衔接数据准备或资源清理。 ```vue 内容 ``` 快速切换 `show` 时,当前动画会被取消,并触发对应的 `enter-cancelled` 或 `leave-cancelled`;不要在取消事件中假定动画已完成。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ---------------- | -------------------------- | ---------------------------- | -------------- | | `show` | 是否显示内容 | `boolean` | `true` | | `name` | 预设动画名 | `string` | `fade` | | `duration` | 时长;对象可分别设置进出场 | `number \| { enter, leave }` | `300` | | `timingFunction` | 动画曲线 | `string` | Snake 标准曲线 | | `delay` | 延迟时间,单位 ms | `number` | `0` | | `appear` | 首次显示是否执行动画 | `boolean` | `false` | | `customClass` | 自定义类名 | `string` | `''` | | `customStyle` | 根节点样式 | `string \| object \| array` | `''` | ### Events | 事件名 | 触发时机 | 参数 | | ---------------------------------------- | -------------------- | ------- | | `before-enter` / `enter` / `after-enter` | 进入动画各阶段 | - | | `before-leave` / `leave` / `after-leave` | 离开动画各阶段 | - | | `enter-cancelled` / `leave-cancelled` | 动画被反向切换而取消 | - | | `click` | 点击根节点 | `event` | ### Slots | 插槽名 | 说明 | | --------- | -------------- | | `default` | 执行过渡的内容 | ## 主题变量 组件未直接使用 CSS 主题变量。可通过 `customClass` 和 `customStyle` 设置内容容器样式。 # Upload 文件上传 用于选择、预览和上传图片、视频或文件。支持普通接口上传与 OSS 等自定义上传。 ## 使用建议 小文件和少量图片可自动上传;批量文件、弱网或需要二次确认的场景使用手动上传。签名、鉴权和文件存储策略必须由业务服务处理,不要写入前端示例。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 ```vue ``` 组件通过 `uni.uploadFile` 上传,支持 `header`、`formData`、`name`、`timeout`、进度、失败重试和手动上传。 ## OSS 自定义上传 OSS 凭证和签名由业务端处理,组件只负责文件队列与状态: ```vue ``` `uploadRequest` 返回远程 URL 字符串,或 `{ url, response?, name? }`。抛出错误时文件进入失败状态,可调用 `retry(index)` 或 `reUpload(index)`。 ## 手动上传 ```vue 开始上传 ``` ## 选择校验与失败重试 `max-count` 和 `max-size` 在文件进入队列前校验;分别监听 `on-exceed`、`on-oversize` 处理业务提示。上传失败的文件保留在队列中,可通过组件实例 `retry(index)` 重试。 ```vue ``` ```ts function onOversize(file) { uni.showToast({ title: `${file.name} 超过 5 MB`, icon: 'none' }); } function onUploadError(_error, index) { // 可在用户点击“重试”后调用 uploadRef.value?.retry(index) } ``` ## 自定义选择入口 设置 `custom-choose` 后,组件不再调用系统文件选择器,而是通过 `on-choose` 将当前限制条件交给业务;业务取得文件后调用 `addFiles(files)` 加入队列。 ## 无障碍 - 自定义选择入口时使用可点击控件并提供明确文案,例如“选择商品图片”。 - 上传进度、成功和失败不能只靠颜色区分;失败项需要提供重试或移除操作。 - 对文件类型、数量和大小的限制应在选择前说明,并在失败信息中给出可执行的修正方式。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ------------------------------------- | ----------------------------------------------------------- | -------------------------------------- | ----------------------------- | | `modelValue` | 文件列表,支持 `v-model` | `UploadFileItem[]` | `[]` | | `fileList` | 初始文件列表(旧版兼容,`modelValue` 有值时优先) | `UploadFileItem[]` | `[]` | | `action` | 服务器上传地址 | `string` | `''` | | `uploadRequest` | 自定义上传适配器(OSS 等),优先于 `action` | `UploadRequest` | - | | `timeout` | 默认上传的超时时间,单位毫秒 | `number` | `60000` | | `accept` | 接受的文件类型 `image / video / file / media / all` | `string` | `'image'` | | `mode` | 展示模式 `grid / list` | `string` | `'grid'` | | `width` / `height` | 单个格子宽高,单位 rpx | `number \| string` | `200` | | `maxCount` | 最大文件数量 | `number \| string` | `52` | | `maxSize` | 单个文件最大字节数 | `number \| string` | `Number.MAX_VALUE` | | `multiple` | 是否开启文件多选 | `boolean` | `true` | | `disabled` | 是否禁用组件 | `boolean` | `false` | | `autoUpload` | 选择完是否自动上传 | `boolean` | `true` | | `deletable` | 是否显示删除按钮 | `boolean` | `true` | | `delIcon` / `delBgColor` / `delColor` | 删除按钮图标 / 背景色 / 图标色 | `string` | `'close'` / error 色 / `#fff` | | `showConfirm` | 删除前是否显示确认弹窗 | `boolean` | `true` | | `showTips` | 是否自动提示 toast | `boolean` | `true` | | `showProgress` | 是否显示上传进度条 | `boolean` | `true` | | `showUploadList` | 是否显示组件内部的文件预览列表 | `boolean` | `true` | | `showFileName` | 是否显示文件名 | `boolean` | `true` | | `showFileSize` | 是否显示文件大小 | `boolean` | `false` | | `previewFullImage` | 是否可通过 `uni.previewImage` 预览图片 | `boolean` | `true` | | `previewFile` | 是否可预览非图片文件 | `boolean` | `true` | | `customBtn` | 是否自定义选择按钮,`true` 时使用 `addBtn` 插槽 | `boolean` | `false` | | `uploadText` | 选择按钮提示文字 | `string` | 按 `accept` 自动 | | `imageMode` | 预览图片显示模式 | `string` | `'aspectFill'` | | `imageShape` | 图片/图标形状 `square / circle` | `string` | `'square'` | | `index` | 各回调事件的最后一个参数,用于区分组件实例 | `string \| number` | `''` | | `header` | 上传请求头 | `object` | `{}` | | `formData` | 上传附加参数 | `object` | `{}` | | `name` | 文件字段名,供后端获取 | `string` | `'file'` | | `sizeType` | `original` 原图 / `compressed` 压缩图 | `string[]` | `['original', 'compressed']` | | `sourceType` | 来源 `album` 相册 / `camera` 相机 | `string[]` | `['album', 'camera']` | | `limitType` | 允许的文件后缀,优先级高于 `accept` 内置格式限制 | `string[]` | `[]` | | `extension` | 选择文件的扩展名过滤,仅 H5 与微信 `accept='file'` 有效 | `string[]` | `[]` | | `fileIconMap` | 文件类型图标映射 `{ [type]: { name, color? } }` | `object` | `{}` | | `compressed` | 选择视频时是否压缩 | `boolean` | `true` | | `maxDuration` | 选择视频时拍摄最长时长,单位秒 | `number` | `60` | | `camera` | 选择视频时摄像头方向 `front / back` | `string` | `'back'` | | `beforeUpload` | 上传前钩子,返回 `false` 或 Promise 拒绝则跳过该文件 | `(index, files) => boolean \| Promise` | - | | `beforeRemove` | 删除前钩子,返回 `false` 或 Promise 拒绝则阻止删除 | `(index, files) => boolean \| Promise` | - | | `toJson` | 返回值为 json 字符串时自动转为对象 | `boolean` | `true` | | `customChoose` | 自定义文件选择,开启后点击触发 `on-choose` 而不调用默认 API | `boolean` | `false` | | `isCustomUpload` | 旧版兼容:选择文件走 `customUpload` 事件 | `boolean` | `false` | | `customClass` / `customStyle` | 自定义类名和样式 | `string \| style` | `''` | ### Events | 事件名 | 说明 | 参数 | | -------------------- | ---------------------------------- | --------------------------------------- | | `update:modelValue` | 文件列表更新,支持 `v-model` | `files` | | `on-choose` | 启用 `customChoose` 时点击选择触发 | `{ accept, maxCount, fileList, index }` | | `on-choose-complete` | 每次文件选择完成后 | `files, index` | | `on-choose-fail` | 文件选择失败 | `error` | | `on-oversize` | 文件超过 `maxSize` | `file, files, index` | | `on-exceed` | 数量超过 `maxCount` | `file, files, index` | | `on-uploaded` | 全部文件上传完毕 | `files, index` | | `on-success` | 单个文件上传成功 | `data, fileIndex, files, index` | | `on-error` | 单个文件上传失败 | `error, fileIndex, files, index` | | `on-change` | 单个文件上传状态改变(无论成败) | `response, fileIndex, files, index` | | `on-progress` | 上传进度变化 | `progress, fileIndex, files, index` | | `on-remove` | 移除文件时 | `fileIndex, files, index` | | `on-preview` | 预览文件时 | `url, files, index` | | `on-list-change` | 文件列表发生变化 | `files, index` | ### Slots | 插槽名 | 说明 | 参数 | | -------- | ---------------------------------- | ------------- | | 默认 | 组件内容(默认渲染文件列表与按钮) | - | | `addBtn` | 自定义选择文件按钮 | - | | `file` | 自定义文件列表 | `file: files` | ### Methods | 方法 | 说明 | | -------------------------- | -------------------------------------------------- | | `upload()` | 上传全部待上传文件 | | `retry(index)` | 重试指定文件 | | `reUpload(index?)` | 重传指定文件或失败队列 | | `addFiles(files)` | 添加外部选择的文件 | | `deleteItem(index)` | 按确认和钩子规则删除文件 | | `remove(index)` | 直接移除指定文件 | | `selectFile()` | 打开文件选择器 | | `clear()` | 清空列表 | | `previewImage(url)` | 预览图片 | | `previewFile(item, index)` | 预览/打开文件 | | `onBeforeRead(file)` | 旧版兼容:把文件交给 `beforeRead`/`afterRead` 流程 | ## 类型定义 从包根导入 `UploadProps`、`UploadFileItem`、`UploadRequest`、`UploadRequestResult`、`UploadExpose` 等类型。 ## 旧版兼容 旧项目仍可使用 `isCustomUpload`、`@customUpload` 和 `onBeforeRead(file)`。新代码推荐使用 `customChoose`/`@on-choose`/`addFiles` 处理自定义选择,使用 `uploadRequest` 处理 OSS 上传。 ## 主题变量 Upload 没有组件专属令牌,直接复用以下全局变量: | 变量 | 用途 | | ------------------------------ | ---------------------- | | `--snake-color-primary` | 选择入口和图片类型标识 | | `--snake-color-success` | 成功及表格文件类型标识 | | `--snake-color-warning` | 演示文稿文件类型标识 | | `--snake-color-error` | 删除、失败和错误状态 | | `--snake-color-info` | 通用信息文件类型标识 | | `--snake-color-text-secondary` | 文件名和状态文字 | | `--snake-color-text-muted` | 辅助信息与默认文件标识 | | `--snake-color-border` | 文件项和选择入口边框 | | `--snake-color-surface` | 文件项背景 | | `--snake-color-disabled-bg` | 禁用背景 | # uView Pro 组件兼容性审计 审计基准:`D:\development\Projects\UniApp\uView-Pro\src\uni_modules\uview-pro\components`。Snake UI 不依赖 uView 运行时;下表是发布前必须维护的本地兼容性清单,`tests/uview-compatibility-audit.test.mjs` 会校验其覆盖率。 ## 已有对应组件(43) 这些组件均有独立的 Snake 类型契约和实现;后续变更需同时核对 Props、Events、Slots、Expose、默认值和跨端关键行为。已有组件测试覆盖公开类型、独立运行时和重点交互;本批新增 Tabbar 的原生栏替换回归。 | uView Pro | Snake UI | 当前审计结论 | | ------------------- | ----------------------- | --------------------------------------------- | | `u-button` | `snake-button` | 已映射 | | `u-calendar` | `snake-calendar` | 已映射 | | `u-cell-group` | `snake-cell-group` | 已映射 | | `u-cell-item` | `snake-cell-item` | 已映射 | | `u-checkbox` | `snake-checkbox` | 已映射 | | `u-checkbox-group` | `snake-checkbox-group` | 已映射 | | `u-config-provider` | `snake-config-provider` | 已映射 | | `u-count-down` | `snake-count-down` | 已映射 | | `u-empty` | `snake-empty` | 已映射 | | `u-form` | `snake-form` | 已映射 | | `u-form-item` | `snake-form-item` | 已映射 | | `u-icon` | `snake-icon` | 已映射 | | `u-image` | `snake-image` | 已映射 | | `u-index-anchor` | `snake-index-anchor` | 已映射 | | `u-index-list` | `snake-index-list` | 已映射 | | `u-input` | `snake-input` | 已映射 | | `u-line` | `snake-line` | 已映射 | | `u-line-progress` | `snake-line-progress` | 已映射 | | `u-link` | `snake-link` | 已映射 | | `u-loadmore` | `snake-loadmore` | 已映射 | | `u-modal` | `snake-modal` | 已映射 | | `u-navbar` | `snake-navbar` | 已映射 | | `u-no-network` | `snake-no-network` | 已映射 | | `u-notice-bar` | `snake-notice-bar` | 已映射 | | `u-popup` | `snake-popup` | 已映射 | | `u-radio` | `snake-radio` | 已映射 | | `u-radio-group` | `snake-radio-group` | 已映射 | | `u-read-more` | `snake-read-more` | 已映射 | | `u-search` | `snake-search` | 已映射 | | `u-select` | `snake-select` | 已映射 | | `u-skeleton` | `snake-skeleton` | 已映射 | | `u-slider` | `snake-slider` | 已映射 | | `u-sticky` | `snake-sticky` | 已映射 | | `u-subsection` | `snake-subsection` | 已映射 | | `u-swiper` | `snake-swiper` | 已映射 | | `u-switch` | `snake-switch` | 已映射 | | `u-tabbar` | `snake-tabbar` | 已修复:`hideTabBar` 默认开启并安全处理普通页 | | `u-tabs` | `snake-tabs` | 已映射 | | `u-text` | `snake-text` | 已映射 | | `u-textarea` | `snake-textarea` | 已映射 | | `u-toast` | `snake-toast` | 已映射 | | `u-transition` | `snake-transition` | 已映射 | | `u-upload` | `snake-upload` | 已映射 | ## uView 独有组件(56) ### P0:高频页面基础能力 `u-action-sheet`、`u-badge`、`u-field`、`u-grid`、`u-grid-item`、`u-number-box`、`u-picker`、`u-rate`。 ### P1:常用扩展能力 `u-avatar`、`u-back-top`、`u-card`、`u-circle-progress`、`u-collapse`、`u-collapse-item`、`u-count-to`、`u-divider`、`u-dropdown`、`u-dropdown-item`、`u-fab`、`u-keyboard`、`u-pagination`、`u-row`、`u-col`、`u-step`、`u-steps`、`u-swipe-action`、`u-tag`、`u-top-tips`、`u-verification-code`。 ### P2:低频、平台特化或可由现有组件组合 `u-action-sheet-item`、`u-alert-tips`、`u-avatar-cropper`、`u-car-keyboard`、`u-city-select`、`u-column-notice`、`u-full-screen`、`u-gap`、`u-lazy-load`、`u-loading`、`u-loading-popup`、`u-mask`、`u-message-input`、`u-number-keyboard`、`u-root-portal`、`u-row-notice`、`u-safe-bottom`、`u-section`、`u-status-bar`、`u-table`、`u-tabs-swiper`、`u-td`、`u-th`、`u-time-line`、`u-time-line-item`、`u-tr`、`u-waterfall`。 ## Snake 专属组件 商城、CMS、筛选、活动和页面装修组件属于 Snake UI 产品能力,不应视为 uView 缺失项。后续仅在自身文档和契约测试中维护它们。 ## cms # 轮播图 用于带自动播放、循环和指示器的图片轮播。 ## 完整信封 ```ts { component: 'v2.carousel', text: '轮播图', type: '3-2', active: true, props: { play: { autoplay: true, interval: 3, loop: true }, indicator: { type: 'bullets', color: '#1989fa' }, style: { heightMode: 'auto', height: 200, pageMargin: 0, imageRadius: 0, backgroundColor: '#FFFFFF' }, items: [{ id: 'slide-1', src: 'https://example.com/a.png', link: { httpType: 11, http: 'https://example.com' } }] } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ----------------- | ---------------------------------------------------- | ----------- | -------------- | | `play.autoplay` | `boolean` | `true` | 自动播放 | | `play.interval` | `number` | `3` | 播放间隔,秒 | | `play.loop` | `boolean` | `true` | 循环播放 | | `indicator.type` | `'none' \| 'bullets' \| 'fraction' \| 'progressbar'` | `'bullets'` | 指示器类型 | | `indicator.color` | `string` | `'#1989fa'` | 指示器颜色 | | `style.*` | [共享图片样式](/cms/data-contract#共享图片样式) | - | 视觉样式 | | `items` | `CmsV2ImageItem[]` | `[]` | 轮播图片及链接 | 运行时把秒转换为 swiper 使用的毫秒。 `progressbar` 在轮播底部显示当前页进度;未提供图片时不显示进度条。省略 `indicator.type` 时使用圆点指示器。 # 优惠券 查询领取资格,以页面或弹窗形态显示领取前后图片,并调用宿主优惠券服务。 ## 完整信封 ```ts { component: 'v2.coupon', text: '优惠券', type: '4-1', active: true, props: { mode: 'page', popupMode: 'bottom', coupon: { id: 'coupon-1', name: '新人券' }, before: { image: 'https://example.com/before.png', link: { httpType: 10, http: '' } }, after: { image: 'https://example.com/after.png', link: { httpType: 10, http: '/pages/coupons' } } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ------------------- | ---------------------- | ---------- | -------------- | | `mode` | `'page' \| 'popup'` | `'page'` | 页面或弹窗展示 | | `popupMode` | `'bottom' \| 'center'` | `'bottom'` | 弹窗位置 | | `coupon` | `object \| null` | `null` | 优惠券对象 | | `before.image/link` | `string / CmsV2Link` | 空值 | 领取前状态 | | `after.image/link` | `string / CmsV2Link` | 空值 | 领取后状态 | `coupon` 可包含 `id/name/newUser/startDate/endDate/url/content/remark`,实际接口字段由宿主适配。领取依赖 [coupon service](/cms/services#优惠券服务),领取后跳转依赖 link service。 # 自定义模块 用命名插槽把区块交给宿主应用渲染。 ## 完整信封 ```ts { component: 'v2.custom', text: '自定义模块', type: '3-8', active: true, props: { slotName: 'member-card' } } ``` ```vue ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ---------- | -------- | ---------- | ------------ | | `slotName` | `string` | `'custom'` | 宿主命名插槽 | 插槽名应来自受控编辑器配置,不要把它当成动态组件名称。 # CMS 页面数据协议 ## 页面信封 新页面推荐使用 v2 信封(以下为协议示意类型,公开的容器入参类型为 `CmsComponentConfig`): ```ts interface CmsV2Block { id?: string | number; component: `v2.${string}`; text?: string; type?: string; active?: boolean; props: Record; } ``` ```ts const pageComponents = [ { id: 'notice-1', component: 'v2.notice', text: '公告', type: '3-6', active: true, props: { direction: 'row', noticeText: '今日上新', link: { httpType: 10, http: '/pages/new/index' }, textList: [], isLeftIcon: true, style: { height: 72, pageMargin: 10, backgroundColor: '#eaf1ff', textColor: '#2d57e7' } } } ]; ``` `component` 和 `props` 是运行时契约。`text`、`type` 用于编辑器展示和分类,运行时不会用它们选择渲染器。`active` 省略时按启用处理。 ## 链接 ```ts interface CmsV2Link { httpType: 10 | 11; http: string; } ``` - `10`:宿主内部导航。 - `11`:外部链接。 - 空 `http` 不执行跳转。 所有跳转最终由 [link service](/cms/services#链接服务) 执行,区块不直接绑定业务路由。 ## 图片项与文本项 ```ts interface CmsV2ImageItem { id?: string | number; src: string; link: CmsV2Link; } interface CmsV2TextItem { text: string; link: CmsV2Link; } ``` ## 共享图片样式 `images`、`carousel` 和 `video` 使用同一组视觉字段: | 字段 | 类型 | 默认值 | 说明 | | ----------------------- | ------------------- | ----------- | ---------------- | | `style.heightMode` | `'auto' \| 'fixed'` | `'auto'` | 自适应或固定高度 | | `style.height` | `number` | `200` | 固定高度,rpx | | `style.pageMargin` | `number` | `0` | 左右页边距,rpx | | `style.imageRadius` | `number` | `0` | 圆角,rpx | | `style.backgroundColor` | `string` | `'#FFFFFF'` | 背景颜色 | 编辑器画布的半尺寸预览值不会落库,消费端不要再次除以二。 ## 版本共存 `snake-cms` 可以在同一页面中渲染 v1 和 v2 区块。v1 使用未带 `v2.` 前缀的 `component` 和 `setStyle`,例如 `{ component: 'images', setStyle: { imageList: [] } }`;v2 使用 `{ component: 'v2.images', active: true, props: { ... } }`。v1 可通过 `visible: false` 或 `setStyle.showComponent: false` 隐藏,v2 使用 `active: false`。 宿主应在数据进入 `snake-cms` 前校验数组和对象;新配置使用 v2,已有 v1 页面无需一次性迁移。 # 分割线 合并辅助空白和分割线两种能力。 ## 完整信封 ```ts { component: 'v2.divider', text: '分割线', type: '3-7', active: true, props: { mode: 'blank', height: 30, lineStyle: 'solid', margin: 0, style: { lineColor: 'rgb(229, 229, 229)', backgroundColor: 'rgb(255, 255, 255)' } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ----------------------- | --------------------------------- | ------------------ | ------------------ | | `mode` | `'blank' \| 'line'` | `'blank'` | 空白或线条 | | `height` | `number` | `30` | 组件高度,rpx | | `lineStyle` | `'solid' \| 'dashed' \| 'dotted'` | `'solid'` | 线型,仅 line 生效 | | `margin` | `0 \| 1` | `0` | 1 表示左右留边 | | `style.lineColor` | `string` | `rgb(229,229,229)` | 线条颜色 | | `style.backgroundColor` | `string` | `rgb(255,255,255)` | 背景颜色 | # 悬浮按钮 在页面固定位置显示一张可点击图片。 ## 完整信封 ```ts { component: 'v2.floatbutton', text: '悬浮按钮', type: '3-9', active: true, props: { src: 'https://example.com/service.png', link: { httpType: 10, http: '/pages/service' }, position: { right: 0, bottom: 20 }, style: { width: 76, height: 76 } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | -------------------- | ----------- | ------- | ------------- | | `src` | `string` | `''` | 按钮图片 | | `link` | `CmsV2Link` | 空内链 | 点击链接 | | `position.right` | `number` | `0` | 距右百分比 | | `position.bottom` | `number` | `20` | 距下百分比 | | `style.width/height` | `number` | `76/76` | 按钮尺寸,rpx | 固定定位可能受宿主安全区和自定义 tabbar 影响,应在目标页面实测。跳转依赖 [link service](/cms/services#链接服务)。 # CMS 快速接入 Snake CMS 用来把后端保存的页面装修配置渲染成 uni-app 页面。新页面使用 `{ component: 'v2.*', active, props }` 信封;已有 v1 配置仍可渲染,见[版本共存](/cms/data-contract#版本共存)。 ```text 装修编辑器 -> 业务后端 -> 页面接口 -> 数据适配 -> ``` Snake UI 只负责渲染和调度。商品、优惠券和跳转等业务能力仍由宿主应用提供,因此不会绑定具体后端、路由或登录体系。 ## 1. 准备页面数据 CMS 页面由页面信息和有序组件数组组成。每个组件至少要有一个字符串类型的 `component`,并使用 `props` 保存配置。 ```ts import type { CmsComponentConfig, CmsPageInfo } from '@puresnake/snake-ui'; const pageInfo: CmsPageInfo = { pageId: 'home', name: '商城首页' }; const pageComponents: CmsComponentConfig[] = [ { id: 'notice-1', component: 'v2.notice', active: true, props: { direction: 'row', noticeText: '今日上新', textList: [], style: { height: 72, pageMargin: 10, backgroundColor: '#effaf5', textColor: '#176b4b' } } } ]; ``` 远端 JSON 不能直接当成可信类型。下面的页面示例把数组和组件标识校验放在 `normalizeCmsPage()` 中;宿主可按自己的接口结构补充字段转换。 `active === false` 的区块不会渲染。完整字段规则见[页面数据协议](/cms/data-contract)。 ## 2. 在页面中渲染 纯展示组件不需要配置业务服务。下面假设宿主的 `api.pages.detail(id)` 返回已解析的 `{ pageId, pageSetup?, pageComponents }` 对象;请替换为项目中的页面接口: ```vue ``` 页面触底时调用 `loadMore()`。下拉刷新重新请求页面配置;`pageInfo` 或 `pageComponents` 变化时,容器会自动初始化商品数据,无需再次调用 `init()`。如果只想用当前配置重新加载商品,可调用 `init()` 或 `retry()`;页面接口失败时重新调用 `loadPage()`。 ## 3. 按需注入业务服务 图片、公告、富文本等展示组件可以直接渲染。配置中出现业务组件时,再注入对应服务: | 服务 | 使用场景 | | ---------- | -------------------------------------- | | `commerce` | 商品列表、活动场次、筛选、商品详情跳转 | | `coupon` | 查询优惠券状态、领取优惠券 | | `link` | 站内链接、外链、小程序和 URL Scheme | 服务应在 `main.ts` 中集中配置。下面只接入商品列表;接口字段不同的项目,也在这里转换成 Snake CMS 需要的结果结构: ```ts import SnakeUI, { type CmsCommerceService } from '@puresnake/snake-ui'; import { api } from '@/services/api'; const commerce: CmsCommerceService = { async getGoods({ params, pageInfo }) { const result = await api.goods.list({ ...params, pageId: pageInfo.pageId }); return { items: result.items || [], total: result.total, hasMore: result.hasMore }; }, navigateGoods({ item }) { uni.navigateTo({ url: `/pages/goods/detail?id=${item.id}` }); } }; app.use(SnakeUI, { cms: { services: { commerce }, onDiagnostic(diagnostic) { console.warn('[CMS]', diagnostic); } } }); ``` `coupon` 和 `link` 的方法签名、返回结构及完整示例见 [CMS 容器 API](/cms/overview#api)。业务服务必须返回规范结构,不要让装修组件依赖后端原始响应。 ## 4. 处理诊断与失败 至少监听 `diagnostic` 和 `error`,并把 `pageId`、组件标识和错误阶段接入日志平台。常见诊断包括: - `invalid-component`:配置项缺少字符串类型的 `component`。 - `unknown-component`:没有内置组件、别名或扩展实现。 - `duplicate-commerce-section`:页面包含多个商品楼层,只有第一个会渲染。 CMS 会忽略过期请求结果,页面切换或重新初始化后,较早返回的请求不会覆盖当前页面。具体状态、事件和 Ref 方法见 [CMS 容器 API](/cms/overview#api),排错步骤见[常见问题](/guide/troubleshooting)。 ## 上线前检查 - 页面接口异常、空数组和非法 JSON 不会导致整页白屏。 - 每个编辑器组件标识都有内置组件、别名或扩展兜底。 - 商品分页、优惠券状态和跳转服务已在真实接口下验证。 - H5、小程序和 App 的外链及页面滚动行为已在目标平台验证。 - `diagnostic` 和 `error` 已接入日志平台,并能关联 `pageId`。 ## 下一步 - [CMS 容器 API](/cms/overview#api):查看 Props、事件、Ref 方法和服务配置。 - [CMS 组件总览](/cms/overview):选择页面装修区块。 - [页面数据协议](/cms/data-contract):了解信封、链接和共享字段。 - [业务服务接入](/cms/services):接入商品、优惠券和跳转能力。 - [装修编辑器数据对接](/cms/sanke-editor):对接编辑器保存的数据和组件标识。 - [运行环境与能力边界](/guide/compatibility):确认不同平台的可用能力。 # 商品列表 查询驱动的商品楼层,包含受众、数据来源、展现方式、顶部栏、样式和空态。 ## 完整信封 ```ts { component: 'v2.goodslist', text: '商品列表', type: '4-3', active: true, props: { audience: 'all', query: { source: 'activity', activityId: '', activityType: '', activityStatus: 'ing', userRule: 'all', gender: [], low: '', high: '', categoryId: '', brands: [], sellingDays: '', sort: 'auto', pageSize: 20, showOutOfStock: false }, display: { layout: 'grid', columns: 2, cardType: 'sale', subType: '', showAttendance: true, showTag: false }, bars: { filter: false, filterList: [], priceFilter: true, tabs: { enabled: false, list: [] }, activitySession: false, sticky: false }, style: { pageMargin: 5, gap: 10, radius: 0, backgroundColor: '#F8F8F8' }, empty: { mode: 'default', image: '', text: '列表为空', color: '#000000' } } } ``` ## Props:数据来源 | 字段 | 类型 | 默认值 | 说明 | | ---------------------- | ----------------------------------------------------------------- | ------------ | ------------------ | | `audience` | `'all' \| 'new' \| 'old'` | `'all'` | 页面受众 | | `query.source` | `'activity' \| 'condition'` | `'activity'` | 指定活动或条件筛选 | | `query.activityId` | `string \| number` | `''` | 活动 ID | | `query.activityType` | `'' \| 'auction' \| 'down_buy' \| 'fixed_price' \| 'fixed_ratio'` | `''` | 活动类型 | | `query.activityStatus` | `'ing' \| 'finished'` | `'ing'` | 活动状态 | | `query.userRule` | `'all' \| 'new' \| 'old'` | `'all'` | 活动用户规则 | | `query.gender` | `string[]` | `[]` | 性别筛选 | | `query.low/high` | `string \| number` | `''` | 价格区间 | | `query.categoryId` | `string \| number` | `''` | 类目 ID | | `query.brands` | `{ id, name }[]` | `[]` | 品牌 | | `query.sellingDays` | `string \| number` | `''` | 最近上架天数 | | `query.sort` | `'auto' \| 'newest' \| 'highest' \| 'lowest'` | `'auto'` | 排序 | | `query.pageSize` | `number` | `20` | 每页数量 | | `query.showOutOfStock` | `boolean` | `false` | 展示已售商品 | ## Props:展示与顶部栏 | 字段 | 类型 | 默认值 | 说明 | | -------------------------------- | ----------------------------------- | ------------ | -------------------- | | `display.layout` | `'grid' \| 'swipe'` | `'grid'` | 网格或横滑 | | `display.columns` | `2 \| 3` | `2` | 网格列数 | | `display.cardType` | `'sale' \| 'auction' \| 'new'` | `'sale'` | 商品卡类型 | | `display.subType` | `string` | `''` | 拍卖场次子类型 | | `display.showAttendance/showTag` | `boolean` | `true/false` | 出价人数和商品标签 | | `bars.filter` | `false \| true \| 'custom'` | `false` | 筛选栏 | | `bars.filterList` | `{ name }[]` | `[]` | 自定义筛选项 | | `bars.priceFilter` | `boolean` | `true` | 价格筛选 | | `bars.tabs.enabled` | `boolean` | `false` | 启用 tabs | | `bars.tabs.list` | `{ id, label, paramType, value }[]` | `[]` | tabs 参数 | | `bars.activitySession` | `boolean` | `false` | 活动场次栏 | | `bars.sticky` | `boolean` | `false` | 顶部栏吸顶,正向语义 | ## Props:样式与空态 | 字段 | 类型 | 默认值 | 说明 | | ----------------------------- | ------------------------------------- | ------------------------- | ------------ | | `style.pageMargin/gap/radius` | `number` | `5/10/0` | rpx 尺寸 | | `style.backgroundColor` | `string` | `'#F8F8F8'` | 背景色 | | `empty.mode` | `'default' \| 'forSale' \| 'downBuy'` | `'default'` | 空态回退模式 | | `empty.image/text/color` | `string` | `''/'列表为空'/'#000000'` | 空态内容 | 数据、筛选、分页和商品点击依赖 [commerce service](/cms/services#商品服务)。页面触底调用 `snake-cms` 的 `loadMore()`。 # 热区图 在一张背景图上按百分比坐标放置多个可点击区域。 ## 完整信封 ```ts { component: 'v2.hotzone', text: '热区图', type: '3-3', active: true, props: { image: 'https://example.com/map.png', zones: [{ id: 'zone-1', top: 10, left: 5, width: 40, height: 25, httpType: 10, http: '/pages/activity' }] } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ------------------------------- | ------------------ | ------ | ---------------- | | `image` | `string` | `''` | 背景图地址 | | `zones` | `CmsV2Hotzone[]` | `[]` | 热区列表 | | `zones[].id` | `string \| number` | - | 稳定标识 | | `zones[].top/left/width/height` | `number` | - | 0–100 百分比坐标 | | `zones[].httpType` | `10 \| 11` | - | 内部或外部链接 | | `zones[].http` | `string` | `''` | 链接地址 | 坐标超出范围时运行时限制到 0–100。跳转依赖 [link service](/cms/services#链接服务)。 # 图片展示 用于一行一图或 1–4 列图片网格。图片项点击通过 [link service](/cms/services#链接服务) 跳转。 ## 完整信封 ```ts { component: 'v2.images', text: '图片展示', type: '3-1', active: true, props: { layout: { mode: 'single', columns: 2 }, style: { heightMode: 'auto', height: 200, pageMargin: 0, imageRadius: 0, backgroundColor: '#FFFFFF', gap: 8 }, items: [{ id: 'image-1', src: 'https://example.com/a.png', link: { httpType: 10, http: '/pages/a' } }] } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ---------------- | ----------------------------------------------- | ---------- | ---------------------- | | `layout.mode` | `'single' \| 'grid'` | `'single'` | 单列或网格 | | `layout.columns` | `1 \| 2 \| 3 \| 4` | `2` | 网格列数 | | `style.*` | [共享图片样式](/cms/data-contract#共享图片样式) | - | 高度、边距、圆角和背景 | | `style.gap` | `number` | `8` | 图片间距,rpx | | `items` | `CmsV2ImageItem[]` | `[]` | 图片、ID 和链接 | `single` 模式忽略 `columns`。 # 魔方 把图片格按声明式布局组合,并支持按星期和时间段投放覆盖图片。 ## 完整信封 ```ts { component: 'v2.magiccube', text: '魔方', type: '3-11', active: true, props: { layout: 'row', columns: 4, style: { pageMargin: 0, gap: 0, radius: 0, height: 188, backgroundColor: '#FFFFFF' }, play: { interval: 3 }, cells: [{ src: 'https://example.com/a.png', link: { httpType: 10, http: '/pages/a' }, schedules: [] }] } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ------------------------------------ | --------------------- | ----------- | ---------------- | | `layout` | `MagicCubeLayout` | `'row'` | 布局模板 | | `columns` | `1..6` | `4` | row 模式列数 | | `style.pageMargin/gap/radius/height` | `number` | `0/0/0/188` | rpx 尺寸 | | `style.backgroundColor` | `string` | `'#FFFFFF'` | 背景色 | | `play.interval` | `number` | `3` | 多图轮换间隔,秒 | | `cells` | `MagicCubeCell[]` | `[]` | 图片格列表 | | `cells[].src/link` | `string / CmsV2Link` | - | 默认图片与链接 | | `cells[].schedules` | `MagicCubeSchedule[]` | `[]` | 定时覆盖 | | `schedules[].weeks` | `number[]` | `[]` | 星期 1–7 | | `schedules[].startTime/endTime` | `string` | `''` | `HH:mm` 时间段 | `MagicCubeLayout` 可选 `row`、`grid2x2`、`left1right2`、`top1bottom2`、`left1right3`、`left2right1`、`left3right1`。定时项还包含自己的 `src` 和 `link`。跳转依赖 [link service](/cms/services#链接服务)。 # 公告 支持横向公告和纵向文本轮播。 ## 完整信封 ```ts { component: 'v2.notice', text: '公告', type: '3-6', active: true, props: { direction: 'row', noticeText: '今日上新', link: { httpType: 10, http: '/pages/new' }, textList: [], isLeftIcon: true, style: { height: 72, pageMargin: 10, backgroundColor: 'rgb(234, 241, 255)', textColor: 'rgb(45, 87, 231)' } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ----------------------- | ------------------- | ------------------ | ------------- | | `direction` | `'row' \| 'column'` | `'row'` | 横向或纵向 | | `noticeText` | `string` | 提示文本 | 横向内容 | | `link` | `CmsV2Link` | 空内链 | 横向点击链接 | | `textList` | `CmsV2TextItem[]` | `[]` | 纵向轮播项 | | `isLeftIcon` | `boolean` | `true` | 左侧公告图标 | | `style.height` | `number` | `72` | 高度,rpx | | `style.pageMargin` | `number` | `10` | 左右边距,rpx | | `style.backgroundColor` | `string` | `rgb(234,241,255)` | 背景颜色 | | `style.textColor` | `string` | `rgb(45,87,231)` | 文本颜色 | 横向或文本项点击依赖 [link service](/cms/services#链接服务)。 # CMS 组件总览 页面把 SankeEditor 保存的 `{ component: 'v2.*', active, props }` 数组交给 ``,由容器按配置渲染对应区块。已有 v1 配置也可继续使用。 > 这里列出的是 `snake-cms` 的 v2 配置能力,不是独立 easycom 标签;v2 区块的组件标识必须带 `v2.` 前缀。 ## 平台兼容性 | H5 | App | 微信小程序 | 支付宝小程序 | | :-: | :-: | :--------: | :----------: | | √ | √ | √ | √ | ## 基础用法 页面配置使用 `{ component, active, props }` 信封;纯展示页面不要求配置请求或缓存: ```vue ``` ## 注入业务服务 推荐在安装 Snake UI 时统一配置。服务接收规范化后的组件配置和页面上下文,接口地址、响应转换、详情路由均由应用决定: ```ts import SnakeUI from '@puresnake/snake-ui'; app.use(SnakeUI, { cms: { cachePrefix: 'my-app:cms', services: { commerce: { async getActivities({ params }) { const data = await api.activity.list(params); return { items: data.items }; }, async getFilters({ component, params }) { return api.filter.list(component.props.query, params); }, async getGoods({ component, params }) { const data = await api.goods.list(component.props.query, params); return { items: data.items, total: data.total }; }, navigateGoods({ item, index, pageInfo }) { uni.navigateTo({ url: `/pages/goods/detail?id=${item.id}&index=${index}&pageId=${pageInfo.pageId}` }); } }, coupon: { async check({ config }) { return api.coupon.check(config.coupon?.id); }, async receive({ config }) { return api.coupon.receive(config.coupon?.id); } }, link: { open(action) { // 在这里统一处理站内、小程序、外链和 URL Scheme } } } } }); ``` 单个实例也可通过 `cms-options` 覆盖全局配置。完整服务契约见[业务服务接入](/cms/services)。 ## API ### Props | 参数 | 说明 | 类型 | 默认值 | | ----------------------- | -------------------------------------- | ---------------------- | ------ | | `pageInfo` | 页面 ID、名称和页面级业务信息 | `CmsPageInfo` | `{}` | | `pageComponents` | 按顺序排列的装修配置 | `CmsComponentConfig[]` | `[]` | | `scrollTop` | 页面滚动位置 | `number` | `0` | | `stickyOffsetTop` | 商品区和搜索框吸顶顶部偏移 | `number` | `0` | | `stickyCustomNavHeight` | 自定义导航栏高度,px | `number` | `0` | | `cmsOptions` | 当前实例的服务、别名、资源和规范化配置 | `CmsOptions` | `{}` | ### Events | 事件 | 参数 | 说明 | | -------------- | ----------------- | ---------------------------------- | | `ready` | `CmsStateChange` | 本轮初始化首次进入可展示状态 | | `state-change` | `CmsStateChange` | 加载状态、页码或商品数量变化 | | `diagnostic` | `CmsDiagnostic` | 配置无效、未知组件或重复商品区 | | `error` | `CmsError` | 活动、筛选、商品、优惠券或跳转失败 | | `goods-click` | `{ item, index }` | 点击商品;随后调用宿主导航服务 | | `offer-click` | `{ item, index }` | 点击拍卖报价;随后调用宿主导航服务 | ### Expose | 方法 | 说明 | | ------------------------------- | ---------------------------- | | `init()` | 重新初始化当前 CMS 页面 | | `loadMore()` | 在 `ready` 状态加载下一页 | | `retry()` | 错误后重新初始化 | | `refreshQuotePay(price, index)` | 更新列表中指定商品的当前报价 | 同时暴露只读的 `auctionSetParams`。 ### Slots | 插槽名 | 说明 | 参数 | | ------------ | --------------------------- | -------------------- | | 配置的插槽名 | 渲染 `v2.custom` 自定义内容 | `{ item }` | | `extension` | 渲染未注册的扩展组件 | `{ item, pageInfo }` | ## 内容区块 | 技术标识 | 文档 | 用途 | | -------------- | ----------------------- | ---------------------- | | `v2.images` | [图片展示](/cms/images) | 单图、纵向图片或网格 | | `v2.carousel` | [轮播图](/cms/carousel) | 自动播放、循环和指示器 | | `v2.video` | [视频](/cms/video) | 视频、封面和自动播放 | | `v2.hotzone` | [热区图](/cms/hotzone) | 图片百分比点击区域 | | `v2.magiccube` | [魔方](/cms/magiccube) | 多布局图片格与定时投放 | | `v2.notice` | [公告](/cms/notice) | 横向公告或纵向轮播 | | `v2.divider` | [分割线](/cms/divider) | 辅助空白和线条 | | `v2.richtext` | [富文本](/cms/richtext) | HTML 图文内容 | ## 互动区块 | 技术标识 | 文档 | 用途 | | ---------------- | ---------------------------- | ------------------------ | | `v2.search` | [搜索框](/cms/search) | 搜索入口、热词和右侧图标 | | `v2.floatbutton` | [悬浮按钮](/cms/floatbutton) | 页面固定图片按钮 | | `v2.popup` | [页面弹窗](/cms/popup) | 居中或底部图片弹层 | | `v2.custom` | [自定义模块](/cms/custom) | 宿主命名插槽 | ## 商城区块 | 技术标识 | 文档 | 用途 | | -------------- | -------------------------- | -------------------------- | | `v2.coupon` | [优惠券](/cms/coupon) | 查询和领取优惠券 | | `v2.goodslist` | [商品列表](/cms/goodslist) | 查询、筛选、分页和商品展示 | ## 扩展组件 未知组件不会让页面崩溃。容器会发出 `unknown-component` 诊断,并交给静态 `extension` 插槽渲染: ```vue ``` 这是跨端扩展点;不要在微信小程序端依赖 ``。 ## 状态与并发 商品区状态为 `idle`、`initial-loading`、`ready`、`empty`、`loading-more`、`no-more` 或 `error`。每次初始化都会生成新的请求代次,旧请求即使晚返回也不会覆盖新页面数据。筛选缓存使用 `cachePrefix:pageId:componentId:filters` 命名空间。 ## 主题变量 | 变量名 | 说明 | | ------------------------------ | -------------------------- | | `--snake-color-background` | 页面及商品区默认背景色 | | `--snake-color-text` | 激活标签文字颜色 | | `--snake-color-text-secondary` | 未激活标签文字颜色 | | `--snake-color-primary` | 商品筛选等强调状态的主题色 | ## 通用规则 - 尺寸采用 750 设计稿基准,运行时按 rpx 使用。 - `active: false` 的区块不会渲染。 - 链接统一为 `{ httpType: 10 | 11, http: string }`。 - 远端 JSON 仍需在宿主边界做数组和对象校验。 - 未识别的 `v2.*` 会产生 `unknown-component` 诊断并进入 extension 插槽。 继续阅读 [页面数据协议](/cms/data-contract) 和 [业务服务接入](/cms/services)。 # 页面弹窗 以底部或居中模式显示一张可点击图片。 ## 完整信封 ```ts { component: 'v2.popup', text: '弹窗', type: '4-2', active: true, props: { image: 'https://example.com/popup.png', link: { httpType: 11, http: 'https://example.com' }, popupMode: 'center' } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ----------- | ---------------------- | ---------- | ------------ | | `image` | `string` | `''` | 弹窗图片 | | `link` | `CmsV2Link` | 空内链 | 图片点击链接 | | `popupMode` | `'bottom' \| 'center'` | `'bottom'` | 弹出位置 | 用户可关闭弹窗;点击图片依赖 [link service](/cms/services#链接服务)。 # 富文本 渲染编辑器保存的 HTML 图文内容。 ## 完整信封 ```ts { component: 'v2.richtext', text: '富文本', type: '3-10', active: true, props: { content: '

品牌故事

', style: { backgroundColor: '#FFFFFF' } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ----------------------- | -------- | ----------- | --------- | | `content` | `string` | `''` | HTML 内容 | | `style.backgroundColor` | `string` | `'#FFFFFF'` | 背景颜色 | 仅渲染可信编辑器输出;外部 HTML 应在服务端清洗。 # 装修编辑器数据对接(SankeEditor) SankeEditor 负责编辑页面配置,Snake UI 负责在 C 端消费配置并渲染。页面以编辑器 `components/v2` 输出为准,编辑器自身 API 以其仓库文档为准。 ## 端到端链路 ```text SankeEditor --save--> 宿主后端 --load--> 页面适配层 --> pageSetup pageInfo pageComponents pageComponents ``` 1. 编辑器通过 `save` 提供 `{ pageSetup, pageComponents }`。 2. 宿主后端保存页面信息和有序组件数组。 3. C 端拉取数据并完成 JSON 解析、默认值和业务字段适配。 4. 页面把 `pageInfo` 与 `pageComponents` 传给 `snake-cms`。 如果现有后端使用 `templateJson` 保存页面设置、使用 `component` 保存组件数组,应在页面适配层还原,而不是让 UI 组件理解后端字段名。 ## 组件数据契约 ```ts { component: 'v2.hotzone', text: '热区图', type: '3-3', props: { image: 'https://example.com/map.png', zones: [] }, active: true } ``` C 端主要消费 `component`、`active` 与 `props`。`text` 和 `type` 用于编辑器展示和分类;面板路由键按约定推导,不应落库。完整规则见 [页面数据协议](/cms/data-contract)。 ## 内置组件标识 | `component` | 渲染内容 | 额外依赖 | | ---------------- | ---------- | ------------------------- | | `v2.images` | 图片展示 | 图片链接需要 link service | | `v2.carousel` | 轮播图 | 图片链接需要 link service | | `v2.video` | 视频 | 无 | | `v2.hotzone` | 热区图 | link service | | `v2.magiccube` | 魔方布局 | link service | | `v2.notice` | 公告 | link service | | `v2.divider` | 分割线 | 无 | | `v2.richtext` | 富文本 | 无 | | `v2.search` | 搜索框 | link service | | `v2.floatbutton` | 悬浮按钮 | link service | | `v2.popup` | 页面弹窗 | link service | | `v2.custom` | 自定义模块 | 命名插槽 | | `v2.coupon` | 优惠券 | coupon/link service | | `v2.goodslist` | 商品列表 | commerce service | 字段详情见 [CMS 组件总览](/cms/overview)。 ## 注入业务服务 推荐在安装插件时集中配置: ```ts app.use(SnakeUI, { cms: { services: { commerce: { async getGoods({ params, pageInfo }) { return api.getGoods({ ...params, pageId: pageInfo.pageId }); }, async navigateGoods({ item }) { uni.navigateTo({ url: `/pages/goods/detail?id=${item.id}` }); } }, coupon: { check: couponApi.check, receive: couponApi.receive }, link: { async open(action) { await openLinkForCurrentPlatform(action); } } } } }); ``` 也可以通过组件的 `cms-options` 覆盖当前页面。 ## 页面接入 ```vue ``` 建议把 `diagnostic` 和 `error` 接入日志平台。未知组件不会静默变成其他组件,而是报告诊断并交给 `extension` 插槽兜底。 ## 链接约定 装修数据统一保存 `{ httpType, http }`。站内链接可以使用 Snake UI 路由工具;外链、小程序和 scheme 应统一交给 link service,避免业务组件各自判断平台。 小程序外链通常需要宿主提供 web-view 承载页。`uni.navigateToMiniProgram` 也只在平台支持且权限正确时可用。 ## 扩展编辑器组件 按以下优先级承接新标识: 1. 在 long-editor `components/v2/` 增加 schema、preview 和 panel。 2. 在 Snake UI 增加同名清单项、静态渲染分支和协议文档。 3. 业务私有组件通过 `extension` 作用域插槽渲染。 新增字段必须进入正式协议,不要通过 alias 或 normalizer 隐式转换。 ## 上线检查 - 后端 JSON 能稳定还原成数组,异常数据有默认值和日志。 - 所有编辑器标识都有内置分支、别名或扩展兜底。 - 商品、优惠券、内链、外链和小程序跳转均在真实目标端验证。 - 页面监听 `diagnostic`、`error` 和必要的状态事件。 - 重复商品区、未知组件和服务失败不会造成整页白屏。 排查具体症状见[常见问题](/guide/troubleshooting)。 # 搜索框 提供搜索入口、热词轮播、框内右图和最多两个外部图标。 ## 完整信封 ```ts { component: 'v2.search', text: '搜索框', type: '3-5', active: true, props: { searchText: '请输入商品名称/货号/关键词', link: { httpType: 10, http: '/pages/search' }, isSearch: false, inputType: 'text', textList: [], rightImage: { show: false, src: '', link: { httpType: 10, http: '' }, width: 60, height: 60, borderRadius: 0, marginRight: 0 }, icons: [], style: { position: 0, height: 60, pageMargin: 0, borderRadius: 0, backgroundColor: '#f9f9f9', borderBgColor: '#fff', textColor: '#969799', borderSize: 1, borderColor: '#000', showBorder: true } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ----------------------------------------------------------- | -------------------- | ---------- | ------------------------ | | `searchText` | `string` | 提示文本 | 占位内容 | | `link` | `CmsV2Link` | 空内链 | 搜索入口 | | `isSearch` | `boolean` | `false` | 是否接受回车确认 | | `inputType` | `'text' \| 'number'` | `'text'` | 键盘类型 | | `textList` | `CmsV2TextItem[]` | `[]` | 搜索热词 | | `rightImage` | `SearchImage` | 见示例 | 框内右侧图片、链接与尺寸 | | `icons` | `SearchIcon[]` | `[]` | 框外图标,最多 2 个 | | `style.position` | `0 \| 1` | `0` | 普通或滚动吸顶 | | `style.height/pageMargin/borderRadius/borderSize` | `number` | `60/0/0/1` | rpx 尺寸 | | `style.backgroundColor/borderBgColor/textColor/borderColor` | `string` | 见示例 | 颜色 | | `style.showBorder` | `boolean` | `true` | 显示边框 | `SearchImage` 还包含 `show/src/link/width/height/borderRadius/marginRight`;图标项包含 `src/link/width/height`。所有点击依赖 [link service](/cms/services#链接服务)。 `style.position: 1` 使用容器的 `scrollTop`、`stickyOffsetTop` 和 `stickyCustomNavHeight` 吸顶;`0` 保持普通页面布局。 # CMS 业务服务接入 展示区块可以直接渲染。链接、优惠券和商品数据由宿主通过 `cms.services` 注入,Snake UI 不绑定具体接口、登录体系或路由。 ## 链接服务 CMS 区块把 `{ httpType, http }` 转换为 `CmsLinkAction`:`10` 对应 `navigate`,`11` 对应 `external`。 ```ts const link: CmsLinkService = { open(action) { if (action.type === 'navigate' && action.url) return uni.navigateTo({ url: action.url }); if (action.type === 'external' && action.url) { return uni.navigateTo({ url: `/pages/webview/index?url=${encodeURIComponent(action.url)}` }); } } }; ``` ## 商品服务 `v2.goodslist.props.query` 会被整理为分页请求参数交给 `commerce.getGoods`。宿主负责把后端响应转换为 `{ items, total?, hasMore? }`。 ```ts const commerce: CmsCommerceService = { async getGoods({ params, pageInfo }) { const response = await api.goods.list({ ...params, pageId: pageInfo.pageId }); return { items: response.items || [], total: response.total, hasMore: response.hasMore }; }, navigateGoods({ item }) { return uni.navigateTo({ url: `/pages/goods/detail?id=${item.id}` }); } }; ``` 需要活动场次或筛选元数据时实现 `getActivities`、`getFilters`。分页由 `snake-cms` 的 `loadMore()` 触发。 ## 优惠券服务 v2 优惠券的 `config.coupon` 对应编辑器保存的优惠券对象。为兼容旧服务,v2 适配器也提供同值的 `config.couponObj`;原有 v1 优惠券仍使用 `couponObj`。 ```ts const coupon: CmsCouponService = { async check({ config }) { return api.coupon.check(config.coupon?.id); }, async receive({ config }) { return api.coupon.receive(config.coupon?.id); } }; ``` `check` 返回 `{ claimable, message? }`,`receive` 返回 `{ success, message? }`。 ## 统一安装 ```ts app.use(SnakeUI, { cms: { services: { link, commerce, coupon }, onDiagnostic(diagnostic) { console.warn('[CMS]', diagnostic); } } }); ``` 缺少服务时静态内容仍可显示;依赖服务的操作不会自行猜测接口。 # 视频 渲染单个视频、封面和自动播放设置。 ## 完整信封 ```ts { component: 'v2.video', text: '视频', type: '3-4', active: true, props: { src: 'https://example.com/video.mp4', coverUrl: 'https://example.com/cover.jpg', autoplay: false, style: { heightMode: 'auto', height: 200, pageMargin: 0, imageRadius: 0, backgroundColor: '#FFFFFF' } } } ``` ## Props | 字段 | 类型 | 默认值 | 说明 | | ---------- | ----------------------------------------------- | ------- | ---------------------- | | `src` | `string` | `''` | 视频地址 | | `coverUrl` | `string` | `''` | 封面地址 | | `autoplay` | `boolean` | `false` | 是否自动播放 | | `style.*` | [共享图片样式](/cms/data-contract#共享图片样式) | - | 高度、边距、圆角和背景 | 各端自动播放策略可能受系统静音和用户手势限制。 ## guide # AI 概述 Snake UI 为 AI 编码助手提供可定位、可验证的上下文资料,帮助助手准确选择组件、核对 API,并遵循 uni-app 的跨端约束。它们不会替代源码、类型和测试;遇到实现问题时,仍应以当前仓库内容为准。 ## 提供的资料 | 资料 | 用途 | | ----------------------------- | ---------------------------------------------- | | [Skills](./skills) | 任务路由与开发规则,指导助手按需读取参考资料。 | | [LLM 上下文](./llms) | `llms.txt` 的定位、内容范围和使用方式。 | | `skills/snake-ui/references/` | 按组件、CMS、指南和工具拆分的完整参考资料。 | ## 推荐工作流 1. 从 `llms.txt` 或 reference 索引定位目标能力。 2. 阅读对应 reference 和当前组件源码、类型文件。 3. 实现最小且完整的变更,保留既有公开 API 和平台兼容行为。 4. 运行受影响范围的测试;公开组件或类型变更后,再运行 `pnpm type-check`。 5. 若更新了 `docs/`,同步生成 AI reference。 不要因为组件名称或模板和其他组件库相似,就推断 Snake UI 的 API 或行为。uView Pro 可以用作参考,但 Snake UI 自身的源码、文档与测试才是最终标准。 ## 关键约束 ### 底部导航 `snake-tabbar` 在原生 tabBar 页面默认调用 `uni.hideTabBar()`,由自定义导航栏替代原生栏。修改时需分别核对普通页面、tabBar 页面、`pagePath` 跳转和 `beforeSwitch` 拦截行为。 ### 图标 `snake-icon` 使用 `iconfont.css` 中内联的字库和 `.sicon-*` 类名。图标名称必须同时存在于 `icon-names.ts` 与 `iconfont.css`;不需要也不应添加独立运行时字体文件。 ### CMS 与运行时适配 请求、缓存、配置和 CMS 服务由插件适配器注入。组件库内部不能直接绑定业务 API;服务是否必需、缺失时的行为,应以对应 CMS reference 和运行时实现为准。 ## 验证 ```bash pnpm skill:sync pnpm type-check pnpm test:component-contracts pnpm test:runtime pnpm test:cms pnpm test:component-docs pnpm docs:build ``` H5 构建通过不代表小程序和 App 已验证。涉及布局、原生 tabBar、节点尺寸或条件编译时,应在实际目标平台继续验证。 # CMS 快速接入已迁移 CMS 文档已独立为一级专区,请前往新的 [CMS 快速接入](/cms/getting-started)。 # 代码提示 Snake UI 面向 Vue 3 + TypeScript 开发,组件标签、属性、事件和工具函数都能获得 IDE 补全与类型校验。本文说明提示从哪来、需要什么编辑器配置,以及提示不生效时如何排查。 ## 组件标签补全 组件通过 [easycom](/components/setting#_3-配置-easycom) 按 `snake-` 前缀解析,模板里直接书写标签即可,无需手动注册: ```vue 提交 ``` IDE(Volar)会把 easycom 规则解析到真实的 `.vue` 组件文件,组件内部通过 `defineProps()` 声明的类型即为模板补全来源:属性名、类型、必填性和事件签名都能获得校验与补全。 ## 类型提示 ### 包类型入口 `@puresnake/snake-ui` 的 `package.json` 声明了 `types: index.d.ts`,TypeScript 会自动解析到全部组件与全局类型: - 每个组件导出自己的 `XxxProps` 与 `XxxEmits` 类型。 - 全局 API 声明为 `uni.$snake` 与模板中的 `$snake`、`$themeStyle`。 - npm 安装走包的 types 入口;uni_modules 本地安装由 IDE 直接读取源码类型,无需额外配置。 ### 按需导入组件类型 把 props 和事件抽成对象时,直接导入对应类型: ```ts import type { TabsEmits, TabsProps } from '@puresnake/snake-ui'; const tabsProps: TabsProps = { list: [{ name: '推荐' }], current: 0 }; ``` ### 工具函数与组合式函数 工具和 hooks 走 `@puresnake/snake-ui/libs` 子路径按需导入,类型自动推断,打包时也能 tree-shaking: ```ts import { navTo, toast } from '@puresnake/snake-ui/libs'; import { useLocale, useTheme, useToast } from '@puresnake/snake-ui/libs'; const { setTheme } = useTheme(); ``` 不建议通过 `uni.$snake` 承接业务逻辑调用:全局属性适合模板与便捷访问,模块代码用按需导入获得最完整的类型推断。 ## 编辑器建议 ### VSCode + Volar 推荐使用 VSCode 与官方 Volar 插件开发 Vue 3 项目: - 仅启用 Volar,禁用 Vetur,避免两套语言服务冲突。 - 推荐 ` ``` ## 检查结果 - 按钮正常渲染:easycom 路径正确。 - 按钮具有主题样式:`index.scss` 已生效。 - 点击后出现提示:`app.use(SnakeUI)` 已执行。 - 控制台没有组件解析警告或样式编译错误。 如果某一步失败,先按上述 4 项定位,再查看[常见问题](/guide/troubleshooting)。完整安装选项、手动导入和本地目录结构分别见[安装 Snake UI](/components/install)、[配置](/components/setting)与[组件快速上手](/components/quickstart)。 ## 选择下一步 ### 基础组件接入 - 在[组件总览](/components/intro)中按名称、用途或关键词选择组件。 - 在[全局配置总览](/guide/foundation)中配置主题、语言、HTTP 和运行时能力。 - 先从 [Button](/components/button)、[Form](/components/form) 或 [Popup](/components/popup) 了解标准文档结构。 ### CMS 页面接入 CMS 页面装修复用同一套安装和运行时。完成本页后,继续阅读 [CMS 快速接入](/cms/getting-started),再按[页面数据协议](/cms/data-contract)和[业务服务接入](/cms/services)对齐接口数据。 # 国际化 Snake UI 内置简体中文 `zh-CN` 和英文 `en-US`,用于管理组件库自身的按钮、状态和提示文案。语言状态是响应式的,切换后组件文案会同步更新。 ## 核心行为 - 通过 `setLocale()` 或 `useLocale()` 响应式切换。 - 用户选择自动保存在 `@puresnake/snake-ui-locale`。 - 同名语言包与内置词条深度合并。 - 缺失词条按“当前语言 → `zh-CN` → 原始 key”回退。 - 支持 `{name}` 和 `{0}` 形式的参数插值。 ## 内置语言包结构 语言包由 `name`、`label` 与 `messages` 组成,`messages` 按组件域分组: ```ts const zhCN: Locale = { name: 'zh-CN', label: '简体中文', messages: { common: { confirm: '确定', cancel: '取消', loading: '加载中', empty: '暂无数据' }, image: { loading: '图片加载中', error: '图片加载失败' }, modal: { title: '提示', confirmText: '确认', cancelText: '取消' }, network: { error: '网络请求失败', canceled: '请求已取消' }, search: { placeholder: '请输入关键字', actionText: '搜索' }, noNetwork: { tips: '哎呀,网络信号丢失', retry: '重试' }, calendar: { startText: '开始', endText: '结束', toolTip: '选择日期' } // ... 其余组件域 } }; ``` 覆盖或扩展语言包时使用相同的分组结构,只需要提供要改的词条,其余字段与内置合并。 ## 在应用入口配置 ```ts import SnakeUI from '@puresnake/snake-ui'; app.use(SnakeUI, { locale: { defaultLocale: 'zh-CN' } }); ``` 本地已保存过有效语言时,保存值优先于 `defaultLocale`。设置 `force: true` 可以忽略保存值并强制使用本次配置。 ## 运行时切换 ```ts import { setLocale } from '@puresnake/snake-ui'; const changed = setLocale('en-US'); ``` 语言已注册时返回 `true` 并持久化选择;名称不存在时返回 `false`,当前语言保持不变。 组件内使用 `useLocale()` 可以同时获得 `currentLocale`、`locales`、`setLocale` 和 `t`。完整交互示例见[多语言工具](/tools/use-locale)。 ## 添加或覆盖语言包 ```ts app.use(SnakeUI, { locale: { locales: [ { name: 'en-US', label: 'English', messages: { common: { confirm: 'OK' } } }, { name: 'ja-JP', label: '日本語', messages: { common: { confirm: '確認', cancel: 'キャンセル' } } } ] } }); ``` 相同 `name` 的语言会覆盖元数据,并与已有 `messages` 深度合并。新增语言可以只提供当前项目需要的词条,其余 key 会尝试回退到中文;关键交易页面仍应检查所有可见文案。 ## 翻译和参数插值 ```ts import { translate, useLocale } from '@puresnake/snake-ui'; translate('common.confirm'); translate('checkout.welcome', { name: 'Snake' }); translate('pagination.total', [20]); const { t } = useLocale('checkout'); t('welcome', { name: 'Snake' }); // checkout.welcome ``` `useLocale(namespace)` 会自动为 `t()` 补上命名空间,适合按页面或业务模块组织词条。 ## 与业务国际化协同 Snake UI 只管理组件库文案。业务页面可以继续使用 `vue-i18n` 等方案,在统一的语言切换入口同步业务语言、Snake UI 语言和系统语言。名称不一致时在这一层显式映射,不要让各页面分别维护规则。 ```ts function changeLocale(locale: 'zh-CN' | 'en-US') { i18n.global.locale.value = locale; setLocale(locale); uni.setLocale?.(locale === 'zh-CN' ? 'zh-Hans' : 'en'); } ``` ## API 摘要 | API | 作用 | | --- | --- | | `setLocale(name)` | 切换并持久化已注册语言,返回是否成功 | | `translate(key, replacements?, localeName?)` | 翻译词条并执行参数替换 | | `useLocale(namespace?)` | 获取当前语言、语言列表、`t()` 和切换方法 | | `currentLocale` | 当前语言的响应式引用 | | `locales` | 已注册语言列表的响应式引用 | 全局配置入口见[全局配置总览](/guide/foundation)。 # 介绍 Snake UI 是面向 **uni-app Vue 3** 的移动商城与 CMS 组件库。它既提供按钮、弹层、表单等基础组件,也提供商品、优惠券、装修页面渲染等业务组件。 ## Snake UI 的由来 移动商城项目长期面临同一个问题:基础组件能通用,商品、优惠券、页面装修却总是各项目重复造一遍。Snake UI 把这条线拆成两层——基础 UI 组件开箱即用,业务组件通过注入的服务与宿主项目对接,从而在不绑定后端的前提下复用整条商城组件链路。 如果你只需要基础组件,安装插件、引入样式并配置 easycom 即可;只有使用 CMS 业务能力时,才需要注入请求、缓存或业务服务。 ## 框架优势 - 🚀 **Vue 3 原生**:基于 ` ``` 仓库 demo 通过 `App.root.vue` 配合根包装插件实现,宿主项目也可以按自身页面架构显式包裹,详见[虚拟根组件](/guide/root)。 ## 在样式和脚本中使用 ```scss .card { color: var(--snake-color-text); background: var(--snake-color-surface); border-color: var(--snake-color-border); } ``` ```vue ``` ```ts import { color } from '@puresnake/snake-ui'; console.log(color.primary); ``` 主题切换后,CSS 变量和响应式色板都会更新。写死的十六进制颜色不会随主题变化。 ## 主题与暗色 API | API | 作用 | | --------------------------- | ------------------------------ | | `setTheme(name)` | 切换主题并持久化,返回是否成功 | | `setThemeColor(color)` | 更新当前主题的颜色片段 | | `currentTheme` | 当前主题的响应式引用 | | `themes` | 已注册主题列表 | | `setDarkMode(mode)` | 设置 `light`、`dark` 或 `auto` | | `toggleDarkMode()` | 在明暗模式间快速切换 | | `isDarkMode()` | 返回当前是否渲染暗色 | | `color` | 当前响应式色板 | ## 暗色跟随与持久化 `auto` 会在平台支持时跟随系统主题。主题名和暗色策略分别保存在 `@puresnake/snake-ui-theme` 与 `@puresnake/snake-ui-dark-mode`,重新进入应用后自动恢复。 ## 使用主题生成器 需要可视化配置色板、生成暗色值并导出多套主题时,使用[主题生成器](/guide/theme-generate)。 需要覆盖页面或单个组件的布局、颜色和状态样式时,查看[自定义样式](/guide/custom-style)。 主题未覆盖、颜色未变化等问题见[常见问题](/guide/troubleshooting)。 # 虚拟根组件 uni-app 没有可直接包裹所有页面的应用级根组件。Snake UI 内置 `Root` Vite 插件,在构建时为每个页面自动注入全局根组件,让主题、暗黑模式、全局提示和弹窗在任意页面自动生效,无需逐页添加组件代码。 ## 解决的问题 `snake-config-provider`、`snake-toast`、`snake-modal` 这类组件需要存在于每个页面的根部。传统做法是在每个页面手动添加: - 主题与暗黑模式的 CSS 变量必须逐页包裹才能覆盖页面内容。 - 全局提示、弹窗要在每个页面各放一份,维护成本高,容易遗漏。 - 新增一个全局能力就要改一遍所有页面。 `Root` 把这件事收敛到构建阶段:页面源码保持原样,编译时自动完成根组件注册与包裹。 ## 技术方案 `Root` 是零额外依赖的纯字符串构建插件,分三步完成注入: 1. **注册根组件**:向 `main.ts` 注入 `import GlobalRootView from "./App.root.vue"`,并注册为全局组件 `global-root-view`。 2. **包裹页面模板**:解析每个页面的 SFC,将模板内容包裹进 ``;页面中的 `` 节点会提取到包裹层外部。 3. **加载根组件**:拦截 `App.root.vue` 的模块请求并返回文件内容,模板中的 `` 接收页面内容。 ## 快速上手 ### 1. 创建 App.root.vue 在 `src/` 下创建 `App.root.vue`(与 `App.vue` 同级): ```vue ``` `` 是页面内容的渲染位置,必须保留。 ### 2. 配置 vite.config.ts ```ts import { defineConfig } from 'vite'; import Uni from '@dcloudio/vite-plugin-uni'; // npm 安装:import { Root } from '@puresnake/snake-ui/plugins'; import { Root } from './src/uni_modules/snake-ui/plugins'; export default defineConfig({ plugins: [Root(), Uni()] }); ``` ### 3. 运行 首次启用后重新启动开发服务。之后不需要修改任何页面代码,所有页面会自动被 `` 包裹,`App.root.vue` 中的内容全局生效。 ## 常见场景 ### 全局主题与暗黑模式 把 `ConfigProvider` 放进根组件,主题变量自动覆盖所有页面: ```vue ``` 主题注册与切换见[多主题与暗黑模式](/guide/multi-theme),ConfigProvider 的完整能力见 [ConfigProvider](/components/config-provider)。 ### 全局提示与弹窗 在根组件中挂载 `global` 模式的 toast 和 modal,任意页面通过组合式函数调用: ```vue ``` ```ts import { useModal, useToast } from '@puresnake/snake-ui'; const toast = useToast(); const modal = useModal(); toast.show('操作成功'); modal.confirm({ content: '确认删除?' }); ``` ### 其他全局组件 任何需要出现在每个页面的组件都可以放进 `App.root.vue`:网络状态提示、加载遮罩、回到顶部按钮等。组件越多,`App.root.vue` 越值得保持精简,只放真正的全局能力。 ## 配置项 | 参数 | 说明 | 类型 | 默认值 | | -------------- | -------------------------------- | -------- | ----------- | | `rootFileName` | 根组件文件名(不含 `.vue` 扩展名) | `string` | `'App.root'` | 如需使用其他文件名(如 `App.global.vue`),修改配置即可: ```ts Root({ rootFileName: 'App.global' }); ``` ## 跨端兼容 `Root` 是纯 Vite 构建时插件,在 uni-app 编译之前完成源代码转换,不依赖任何平台特定 API。H5、微信小程序、支付宝小程序、头条/抖音小程序、Android App、iOS App 与鸿蒙 App 均支持。 启用后修改 `pages.json` 会自动重载页面列表,无需手动重启开发服务器。 ## 注意事项 - **`` 必须保留**:它是页面内容的渲染位置,删除后页面不会渲染任何内容。 - **`` 会被提取**:页面模板中的 `` 会移到包裹层外部,确保微信小程序兼容,无需手动处理。 - **Vue 版本要求**:需要 Vue `>= 3.2.13`(使用 `vue/compiler-sfc` 的 `parse` API;HBuilderX 环境下自动降级为正则匹配)。 - **插件顺序**:如果项目还有其他修改 `pages.json` 的插件,请把 `Root()` 放在它们之后。 - **不启用插件时**:也可以在需要主题变量的页面外层显式包裹 `ConfigProvider`,两种方式互斥,不要同时使用。 - **首次启用需要重启**:开发服务需要在配置完成后重启一次,之后才进入自动包裹与 HMR 状态。 ## 下一步 - 根组件的主题注入细节:[ConfigProvider](/components/config-provider) - 主题与暗黑模式:[多主题与暗黑模式](/guide/multi-theme) - 全局配置入口:[全局配置总览](/guide/foundation) # 装修编辑器数据对接已迁移 CMS 文档已独立为一级专区,请前往新的 [装修编辑器数据对接](/cms/sanke-editor)。 # Skills 能力包 Skills 是可复用的 AI 能力包。Snake UI 通过它把组件、CMS、主题、图标和 uni-app 跨端约束整理成 AI 可按需读取的资料,使 AI 能更稳定地理解组件库并生成符合项目约定的代码。 通过 Skills,开发者可以: - 快速让 AI 了解 Snake UI 的组件与使用方式; - 让组件 API、平台差异和关键行为有统一的核对入口; - 减少从其他组件库错误推断 API 的情况; - 在文档更新后自动同步 AI reference,保持上下文可维护。 ## 安装 Skills Snake UI 发布到 GitHub 后,在项目根目录执行: ```bash pnpx skills add purenia-ai/snake-ui --skill snake-ui ``` 安装器会识别仓库中的 `skills/snake-ui/`,并将它安装到所选 AI 编码工具的 Skills 目录。也可以先查看可安装内容: ```bash pnpx skills add purenia-ai/snake-ui --list ``` ## 开源仓库 - GitHub:[purenia-ai/snake-ui](https://github.com/purenia-ai/snake-ui) - 问题反馈:[GitHub Issues](https://github.com/purenia-ai/snake-ui/issues) ## 如何使用 安装后,AI 会根据任务选择所需资料。处理具体组件时,应读取该组件的 reference、当前源码和类型;遇到主题、图标或 CMS 集成,则读取相应指南或 CMS reference。 例如修改 `snake-tabbar` 时,除了组件文档,还要检查原生 tabBar 隐藏、`pagePath`、`beforeSwitch` 与 `switchTab` 的行为;修改图标时,需同步核对 `icon-names.ts` 和内联字库中的 `.sicon-*` 类名。 ## 文件结构 ```text skills/snake-ui/ ├── SKILL.md └── references/ ├── INDEX.md ├── components/ ├── cms/ ├── guide/ └── tools/ ``` `references/INDEX.md` 汇总每份资料的名称、描述和触发关键词。处理单个组件或能力时,AI 优先读取最相关的一两份 reference,而不是加载整个目录。 ## 为什么使用 Skills ### 标准化 每份 reference 都来自当前 VitePress 文档,并配有触发关键词,帮助 AI 以一致方式定位资料和核对公开 API。 ### 可扩展 团队可以在保持 `SKILL.md` 路由规则的前提下,继续补充组件、CMS 或项目专属 reference。 # 主题生成器 主题生成器用于可视化配置一套或多套 Snake UI 主题,并导出可直接注册的 `@puresnake/snake-ui.theme.ts`。 ## 生成步骤 1. 选择或输入主题颜色,并确认颜色选择器。 2. 填写唯一的 `name`,按需补充 `label` 和 `description`。 3. 单主题可直接导出;多主题先逐套加入导出队列。 4. 下载 `@puresnake/snake-ui.theme.ts` 并放入宿主项目。 ## 工具能力 - **分组色票**:按品牌与状态、文本与描边、背景与表面、通知与浮层分组,覆盖完整令牌。 - **智能生成暗色值**:开启暗黑色值后,基于亮色方案智能生成暗黑初始色值,可以逐项覆盖;支持一键刷新。 - **随机主题**:主题色组支持随机生成配色,作为起步方案再逐项调整。 - **导出队列**:配置好一套主题后加入队列,继续配置下一套,最后统一导出多套主题。 - **本地保存**:配置保存在浏览器本地,刷新页面不丢失。 ## 配置工具 ## 注册导出结果 ```ts import SnakeUI from '@puresnake/snake-ui'; import snakeThemePresets from './snake-ui.theme'; app.use(SnakeUI, { theme: { themes: snakeThemePresets, defaultTheme: 'snake', defaultDarkMode: 'light' } }); ``` 导出文件只保留相对默认色板发生变化的令牌,运行时会自动补齐其余颜色。 ## 导出后检查 - 每套主题的 `name` 唯一,且 `defaultTheme` 能找到对应主题。 - 主按钮文字与实心主色有足够对比度。 - 浅色、暗色下的文字、边框、背景和禁用状态都可辨识。 - 在实际 H5、小程序或 App 页面检查,而不只依赖生成器预览。 ::: warning 暗色生成 暗色值由启发式规则生成。复杂品牌色、无障碍要求或关键交易页面应由设计与前端共同复核。 ::: 主题结构和运行时切换方式见[多主题与暗黑模式](/guide/multi-theme)。 # 工具文档已迁移 工具现在拥有独立的顶栏、目录和分组侧边栏,请前往[工具介绍](/tools/intro)。 常用入口: - [HTTP 请求](/tools/http) - [快速使用](/tools/fast-use) - [节流与防抖](/tools/debounce-throttle) - [路由跳转](/tools/route) - [组合式函数](/tools/use-theme) 此页面仅用于兼容旧链接。 # 常见问题 先根据症状检查安装路径、插件注册、全局样式和 easycom。CMS 问题再检查数据与业务服务。 ## 先定位问题类型 | 现象 | 优先检查 | 相关文档 | | -------------------- | ---------------------------------------- | ------------------------------------------ | | 组件未解析或没有样式 | 安装方式、easycom、SCSS 入口 | [快速开始](/components/quickstart) | | 主题颜色没有生效 | `theme.scss`、ConfigProvider、主题变量名 | [多主题与暗黑模式](/guide/multi-theme) | | CMS 页面为空 | 配置信封、组件标识、`diagnostic` 事件 | [CMS 总览](/cms/overview) | | 商品/优惠券操作失败 | `cms.services` 注入和返回契约 | [业务服务接入](/cms/services) | | 仅某个平台异常 | 条件编译、平台 API、真机基础库版本 | [运行环境与能力边界](/guide/compatibility) | 下面按常见症状展开排查。 ## 1. 组件未解析 **现象:** 控制台提示无法解析 `snake-*`,页面显示为空。 1. 确认 `pages.json` 已开启 `easycom.autoscan`。 2. npm 安装使用 `@puresnake/snake-ui/components/...`,本地安装使用 `@/uni_modules/snake-ui/components/...`。 3. 确认组件目录和文件名均为 `snake-组件名`。 4. 修改 `pages.json` 后重启开发服务。 ## 2. 组件有结构但没有样式 确认 `App.vue` 全局样式已导入正确入口: ```scss // npm @import '@puresnake/snake-ui/index.scss'; // 或 uni_modules @import './uni_modules/snake-ui/index.scss'; ``` 两种路径只保留与安装方式对应的一种。HBuilderX 项目还需确认已安装「sass/scss 编译」插件。 ## 3. npm 与 uni_modules 安装混用 **现象:** 依赖重复、版本不一致、打包异常或样式冲突。 - 二选一:npm 安装(CLI 项目)或 uni_modules 安装(HBuilderX 项目),不要同时存在两份。 - 清理 `node_modules` 与 `uni_modules` 中的重复依赖,保持版本唯一。 - 升级到最新版本,避免历史缺陷。 ## 4. 类型提示缺失 **现象:** 组件标签、属性或 `import` 无补全、无校验。 1. 确认安装方式与导入路径一致(npm 用 `@puresnake/snake-ui`,uni_modules 用本地路径)。 2. VSCode 仅启用 Volar,禁用 Vetur。 3. 组件目录名必须为 `snake-组件名`,easycom 才能解析到组件类型。 4. 修改配置或升级依赖后重启 TS 服务或编辑器。 详见[代码提示](/guide/code-hint)。 ## 5. `uni.$snake` 不存在 确认在 `createApp()` 中执行了 `app.use(SnakeUI)`,并且页面使用的 app 实例就是该函数返回的实例。仅配置 easycom 不会安装全局工具。 模块代码也可以绕过全局属性,直接按需导入: ```ts import { navTo, toast } from '@puresnake/snake-ui/libs'; ``` ## 6. 主题切换没有覆盖页面 - 确认已安装 Snake UI 插件并注册主题。 - 页面根节点需要获得主题 CSS 变量;全局主题场景推荐使用 `snake-config-provider` 包裹页面根部,或启用[虚拟根组件](/guide/root)。 - 检查业务样式是否写死十六进制颜色,改用 `var(--snake-color-*)`。 - 检查主题 `name` 是否存在,`setTheme(name)` 返回 `false` 表示没有找到该主题。 详见[多主题与暗黑模式](/guide/multi-theme)。 ## 7. 与其他组件库共存 Snake UI 使用 `snake-` 组件前缀与 `--snake-*` 变量命名空间,与其他库混用时注意: - easycom 规则不要互相覆盖 `snake-*` 前缀。 - 全局样式冲突时缩小引入范围,避免两套 reset/基础样式同时生效。 - 工具函数按需导入,避免挂载到同一个全局对象。 ## 8. HBuilderX 编译或提示异常 - 线上项目使用 HBuilderX 稳定版,内测版仅用于尝鲜。 - 确认已安装「sass/scss 编译」插件。 - HBuilderX 的 TS 提示弱于 Volar;需要完整类型体验时建议 CLI 项目 + VSCode,见[代码提示](/guide/code-hint)。 - 修改 `pages.json` 或 easycom 配置后重新编译项目。 ## 9. CMS 页面为空 依次检查: 1. `pageComponents` 是否为数组。 2. 每项是否包含字符串 `component`。 3. 是否设置了 `active: false`。 4. `component` 是否属于内置标识。 5. 是否监听 `diagnostic` 与 `error` 获取具体原因。 未知组件可以通过 `extension` 插槽承接,不会自动变成内置组件。 ## 10. 商品、优惠券或外链操作失败 这些属于业务能力,不会由基础安装自动提供。请通过 `cms.services.commerce`、`cms.services.coupon` 和 `cms.services.link` 注入。 若错误名为 `UIRuntimeError`,错误消息会指出缺少的适配器及触发组件。 ## 11. 小程序外链打不开 小程序不能像 H5 一样直接打开任意外链。宿主通常需要提供 web-view 页面,并在 `cms.services.link.open()` 中完成平台适配。小程序跳转还需确认目标平台支持 `uni.navigateToMiniProgram` 及相应权限。 ## 仍然无法定位 提交问题时请同时提供:Snake UI 版本、uni-app 编译器版本、目标平台、安装方式、最小复现页面、控制台错误,以及 `diagnostic` / `error` 事件内容。 ## tools # 颜色处理 颜色工具处理三位或六位十六进制颜色,并提供 RGB、RGBA 与渐变计算。 ## 格式转换 ```ts import { colorToRgba, hexToRgb, rgbToHex } from '@puresnake/snake-ui'; hexToRgb('#06d290'); // { r: 6, g: 210, b: 144 } rgbToHex(6, 210, 144); // #06d290 colorToRgba('#06d290', 0.5); // rgba(6, 210, 144, 0.5) ``` `rgbToHex` 会把通道取整并限制在 0–255;非法十六进制输入在 `colorToRgba` 中原样返回。 `hexToRgb` 接受带或不带 `#` 的三位、六位十六进制颜色,解析失败返回 `undefined`。`colorToRgba` 的 `alpha` 默认为 1,并限制在 0–1。需要读取当前主题色而非转换固定颜色时,使用[颜色管理](/tools/use-color)。 ## 颜色渐变 ```ts import { colorGradient } from '@puresnake/snake-ui'; colorGradient('#000000', '#ffffff', 3); // ['#000000', '#808080', '#ffffff'] ``` `steps <= 0` 或颜色无效时返回空数组。 ## API 速查 | 方法 | 返回值 | | ---------------------------------- | ---------------------------------------- | | `hexToRgb(value)` | `{ r, g, b }` 或 `undefined` | | `rgbToHex(r, g, b)` | 六位十六进制字符串 | | `colorToRgba(value, alpha = 1)` | RGBA 字符串;无效颜色原样返回 | | `colorGradient(start, end, steps)` | 渐变颜色数组;`steps = 1` 时只返回起点色 | # 节流与防抖 节流限制一段时间内的执行频率;防抖等待连续操作停止后再执行。滚动和高频点击通常用节流,搜索输入和草稿保存通常用防抖。 ## 防抖 ```ts import { debounce } from '@puresnake/snake-ui'; const search = debounce((keyword: string) => { console.log('搜索建议', keyword); }, 500); search('snake'); search.cancel(); ``` `immediate: true` 会在首个调用立即执行,后续调用只刷新等待窗口。`debounce` 返回的包装函数没有返回业务回调结果;`cancel()` 取消尚未触发的定时调用。 ## 节流 ```ts import { throttle } from '@puresnake/snake-ui'; const measure = throttle(() => { console.log('重新计算布局'); }, 200); ``` 节流函数在窗口外立即执行;等待窗口内首次排队的调用会在窗口结束时执行,后续调用不会替换它的参数。返回函数同样提供 `cancel()`,取消后重置计时基准。 ## 在 Vue 中清理 ```ts import { onBeforeUnmount } from 'vue'; import { debounce } from '@puresnake/snake-ui'; const save = debounce(() => console.log('保存草稿'), 600); onBeforeUnmount(save.cancel); ``` 组件卸载前取消定时器,避免离开页面后继续修改状态。 ## 参数 | 函数 | 参数 | 默认值 | | ------------------------------------- | ------------------------------ | --------------------------------- | | `debounce(callback, wait, immediate)` | 回调、等待毫秒数、是否立即执行 | `wait = 300`,`immediate = false` | | `throttle(callback, wait)` | 回调、窗口毫秒数 | `wait = 300` | 需要在组合式代码中使用时,还可选择[useDebounce 与 useThrottle](/tools/use-rate-limit);这两个封装同样需要手动清理。 # 对象深拷贝 `deepClone(value)` 创建独立副本,支持普通对象、数组、`Date`、`Map`、`Set`、Symbol 键和循环引用。 ```ts import { deepClone } from '@puresnake/snake-ui'; const source = { profile: { name: 'Snake' }, tags: new Set(['new']) }; const copy = deepClone(source); copy.profile.name = 'Pro'; // source.profile.name 仍为 Snake ``` 函数保留对象图中的循环关系,但不会复制类实例的私有语义。业务模型实例应使用其自身的序列化或复制方法。 ## API 与边界 `deepClone(value: T): T` 接受任意值。原始值和函数直接返回;对象、数组、`Date`、`Map`、`Set` 会创建新引用,循环引用及 Symbol 键会保留。`Map` 的键和值也会递归复制。 需要隔离可变配置或快照时使用它。类实例会按普通对象重建,原型方法、私有字段等不会保留;这类数据应使用专门的复制方法。 # 对象深合并 `deepMerge(target, ...sources)` 递归合并普通对象,并返回新对象,不修改输入值。数组、日期和其他值由后一个来源整体替换。 ```ts import { deepMerge } from '@puresnake/snake-ui'; const config = deepMerge( { header: { locale: 'zh-CN' }, tags: ['base'] }, { header: { token: 'abc' }, tags: ['custom'] } ); // { header: { locale: 'zh-CN', token: 'abc' }, tags: ['custom'] } ``` 该函数适合配置合并。需要按主键合并数组时,应在业务层明确实现数组策略。 ## API 与覆盖规则 `deepMerge(target: T, ...sources: Partial[]): T` 从左到右合并来源,返回新对象,输入对象不变。只有前后两侧都是普通对象时才递归合并;数组、`Date`、`Map` 等由后一个来源整体替换为副本。 例如主题默认配置与页面配置可以合并;若要把数组按 `id` 合并,需在调用前明确业务规则。嵌套引用的复制规则见[对象深拷贝](/tools/deep-clone)。 # 事件总线 `createEmitter()` 创建隔离的同步事件总线;`emitter` 是框架提供的共享实例。 ```ts import { createEmitter } from '@puresnake/snake-ui'; const emitter = createEmitter(); const off = emitter.on<{ id: number }>('order:updated', payload => { console.log(payload.id); }); emitter.emit('order:updated', { id: 1 }); off(); ``` 实例提供 `on`、`off`、`emit` 和 `clear`。页面级事件应在卸载时退订;父子组件通信优先使用 Props/Events,跨域共享状态优先使用明确的 store。 ## API 与生命周期 | 方法 | 行为 | | --------------------- | ---------------------------------------------------------------- | | `on(name, handler)` | 注册处理函数;同一事件下重复注册同一函数只保留一次,返回解绑函数 | | `off(name, handler?)` | 删除指定处理函数;不传 `handler` 时删除该事件的全部处理函数 | | `emit(name, payload)` | 同步通知该事件的处理函数,无返回值 | | `clear()` | 删除实例中的全部事件 | `createEmitter()` 每次创建独立实例;导出的 `emitter` 是共享实例。Vue 页面或组件中的订阅应在 `onBeforeUnmount` 中调用 `on()` 返回的解绑函数。处理函数中的异常会同步传给调用方,`emit` 不会替你捕获。 # 快速使用 工具无需单独安装。包根入口与 `@puresnake/snake-ui/libs` 都能按需导出公开能力,应用插件还会安装全局兼容入口。 ## 按需导入 ```ts import { colorToRgba, debounce, route, timeFormat } from '@puresnake/snake-ui'; const submit = debounce(() => save(), 500); const timestamp = timeFormat(Date.now(), 'yyyy-mm-dd'); await route('/pages/result/index', { at: timestamp }); ``` 这是组合式 API、业务模块和可测试代码的首选方式。 ## 全局工具 ```ts import SnakeUI from '@puresnake/snake-ui'; app.use(SnakeUI); uni.$snake.toast('已保存'); await uni.$snake.sleep(300); ``` 模板中可直接使用 `$snake`,但复杂表达式应放回 ` ``` ## 入口建议 | 场景 | 入口 | | ------------------------ | ----------------------------------------------- | | 新的 TypeScript 代码 | 从 `@puresnake/snake-ui` 按需导入 | | 模板中的简单提示或格式化 | `$snake` | | 旧 Options API 项目 | `uni.$snake` 或逐步改为按需导入 | | Vue 响应式状态 | `use*` 组合式函数(如 `useTheme` / `useColor`) | 不要同时维护自定义工具副本和 Snake UI 入口;先确认现有工具是否满足需求,再决定是否封装业务层。 `http` 默认返回完整响应,例子通过 `originalData: false` 显式获取数据体;请在业务 API 层统一约定。组合式函数应在 Vue 组件的 ` ``` | 参数 | 说明 | | ---------- | ---------------------------------------------------- | | `selector` | CSS 选择器 | | `instance` | 可选的组件实例或查询上下文,用于限定查询范围 | | `all` | 默认 `false`,传 `true` 时查询全部匹配节点,返回数组 | ## 返回值与调用时机 `getRect(selector, instance?, all?)` 返回 Promise。单节点查询无结果时得到宽高及坐标均为 0 的兜底对象;`all: true` 无结果时得到空数组,不会因未匹配而拒绝。 应在节点渲染并完成 DOM 更新后调用。需要响应式结果和手动刷新时,使用[useRect](/tools/use-rect)。 # 全局唯一标识符 `guid(prefix = 'snake')` 生成带前缀的客户端标识符。 ```ts import { guid } from '@puresnake/snake-ui'; guid(); // snake-... guid('order'); // order-... ``` ## API 与使用边界 `guid(prefix = 'snake'): string` 返回 `前缀-时间戳-随机段` 形式的字符串。每次调用都会生成新值,适合在创建列表项时生成稳定的前端 `key`: ```ts const item = { id: guid('item'), label: '新项目' }; ``` 不要在每次渲染时重新调用,否则列表 `key` 会变化。它不保证跨系统永久唯一,也不具备密码学安全性;数据库主键和安全令牌应由相应系统生成。 # HTTP 请求 ## uView 风格入口 `http` 是请求模块的规范单例。`snakeHttp` 仅作为兼容别名保留;请求模块默认导出 `httpPlugin`,可通过 `app.use(httpPlugin, { requestConfig, interceptor })` 挂载 `this.$http`;使用 `app.use(SnakeUI)` 时,`$http` 与 `$snake.http` 同时可用。 默认 `meta.originalData` 为 `true`,因此调用方会收到完整的 `uni.request` 响应。传入 `meta: { originalData: false }` 后才返回 `response.data`,且非 2xx 状态会 reject。请求拦截器取消仍会 reject `RequestError`,不会产生永久 pending 的 Promise。 `http` 是面向 uni-app 的轻量请求客户端,支持 TypeScript、全局配置、请求/响应拦截器、Loading、Toast、自定义传输层和多实例。 ## 基础使用 ```ts import { http } from '@puresnake/snake-ui'; interface Goods { id: number; name: string; } const goods = await http.get('/goods', { page: 1 }, { meta: { originalData: false } }); await http.post('/orders', { goodsId: goods[0].id }); ``` `get(url, params, options)` 把第二个参数作为查询数据;`post/put/delete` 把第二个参数作为请求数据。示例显式设置 `originalData: false`,以获得接口数据;默认返回完整 uni-app 响应,不能直接当作商品数组使用。 ## 全局配置 ```ts import SnakeUI from '@puresnake/snake-ui'; app.use(SnakeUI, { http: { config: { baseUrl: 'https://api.example.com', timeout: 20_000, header: { 'content-type': 'application/json' }, meta: { loading: true, toast: true, originalData: false } } } }); ``` 单次请求配置会覆盖全局值,`header` 与 `meta` 做深合并: ```ts await http.post('/login', form, { header: { 'x-device': deviceId }, meta: { loading: false } }); ``` ## 拦截器 ```ts import { configureHttp } from '@puresnake/snake-ui'; configureHttp({ interceptor: { request(options) { return { ...options, header: { ...options.header, Authorization: `Bearer ${token}` } }; }, response(data) { return data; } } }); ``` 请求拦截器返回 `false` 表示取消。响应拦截器可以转换最终返回值,抛出的异常会包装为可识别的 HTTP 错误。 ## 响应与错误 默认 `meta.originalData: true` 时返回完整响应;设置为 `false` 后,任意 HTTP 2xx 返回 `response.data`,其他状态会 reject。传输失败、拦截器失败和取消都会 reject Promise。并发开启 `meta.loading` 时,Loading 会在最后一个请求结束后才关闭。 ```ts import { http, RequestError } from '@puresnake/snake-ui'; try { await http.get('/profile'); } catch (error) { if (error instanceof RequestError) { console.log(error.kind, error.statusCode, error.config, error.platformError); } } ``` `kind` 为 `canceled`、`http`、`transport` 或 `interceptor`。`transport` 错误会保留宿主的原始失败对象到 `platformError`;支付宝小程序的 `errMsg`、网络/证书/域名错误可据此直接排查。Snake 内部的 `baseUrl`、`meta` 与 `params` 不会透传给 `uni.request`。 ## 多实例与自定义传输 ```ts import { Request } from '@puresnake/snake-ui'; const analytics = new Request(); analytics.setConfig({ baseUrl: 'https://events.example.com' }); analytics.setTransport(async options => ({ statusCode: 200, data: { accepted: true, url: options.url }, header: {} })); ``` 自定义 transport 适合测试、离线演示或接入宿主网络层,不需要替换全局 `http`。 ## 推荐的 API 分层 ```ts // api/goods.ts import { http } from '@puresnake/snake-ui'; interface Goods { id: number; name: string; } export const getGoods = (page: number) => http.get('/goods', { page }, { meta: { originalData: false } }); ``` 页面只调用业务 API,不重复处理 base URL、Token 和通用错误。 ## 接口配置表 ```ts import { AutoHttp, http } from '@puresnake/snake-ui'; const api = new AutoHttp.Builder(http).dispatch({ goods: { url: '/goods', method: 'GET' }, detail: { url: '/goods', method: 'GET' } }); await api.goods({ data: { page: 1 } }); await api.detail({ url: () => '/42' }); ``` `AutoHttp.Builder` 根据接口配置表生成请求函数,也支持传入自定义的 Promise 请求函数。 ## 平台说明 默认 transport 依赖 `uni.request`。上传、下载和流式响应不属于当前客户端职责,应使用对应 uni-app API 或宿主适配器。 ## API 速查 | 入口 | 用途 | | ---------------------- | ----------------------------------------------- | | `http` | 全局请求单例,提供 `get/post/put/delete` 等方法 | | `configureHttp(setup)` | 配置全局请求与拦截器 | | `new Request()` | 创建独立配置、拦截器和传输层的客户端 | | `RequestError` | 捕获取消、HTTP、传输或拦截器错误 | 请在项目中统一选择“完整响应”或“数据体”返回约定,并在业务 API 层固定配置,避免同一类型参数对应不同返回形状。 # 工具 Snake UI 把网络请求、通用函数、uni-app 平台封装和组合式函数放在同一个工具域中。每项能力拥有独立页面,便于搜索、收藏和逐项核对。 ## 能力地图 | 分组 | 适合解决的问题 | 推荐入口 | | ---------- | --------------------------------------- | ---------------------------- | | 网络 | 请求配置、拦截器、统一错误处理 | [HTTP 请求](/tools/http) | | 工具库 | 数据、时间、路由、颜色和平台能力 | [快速使用](/tools/fast-use) | | 组合式函数 | 在 Vue 组件中使用主题、语言、弹窗等能力 | [主题管理](/tools/use-theme) | ## 选择调用方式 可复用模块优先按需导入,类型提示最完整,也更容易测试: ```ts import { debounce, deepMerge, route } from '@puresnake/snake-ui'; ``` 安装 Snake UI 后,模板、Options API 和迁移代码也可以使用 `$snake`: ```ts uni.$snake.toast('操作完成'); await uni.$snake.route('/pages/order/detail', { id: 1 }); ``` ## 平台边界 纯函数可以在普通 TypeScript 模块中运行。路由、节点、剪贴板、Toast 和 HTTP 默认传输层依赖对应的 uni-app API;具体限制在各能力页面说明。 ## 从这里开始 - 新项目先阅读[快速使用](/tools/fast-use),确定统一的导入约定。 - 接口接入查看[HTTP 请求](/tools/http)。 - 页面跳转查看[路由跳转](/tools/route),高频调用节流查看[节流与防抖](/tools/debounce-throttle)。 - 纯数据处理可从[对象深合并](/tools/deep-merge)、[时间格式化](/tools/time)或[规则校验](/tools/test)进入。 - 主题、语言及提示分别查看[主题管理](/tools/use-theme)、[多语言](/tools/use-locale)和[useToast](/tools/use-toast)。 # 平台辅助 平台工具封装常见 uni-app 能力,调用前应确认目标平台提供对应 API。 ## 剪贴板、提示与等待 ```ts import { clipboard, sleep, toast } from '@puresnake/snake-ui'; await clipboard('SNK-2026'); toast('复制成功'); await sleep(300); ``` `clipboard` 在 API 不可用或调用失败时拒绝 Promise;`toast(title, duration)` 使用无图标轻提示。 `toast` 默认展示 2000 ms,空标题不会调用平台 API;`sleep(delay = 0)` 返回延时 Promise。`clipboard` 只负责写入剪贴板,若业务需要自定义成功提示,应在成功后自行展示。 ## 系统信息 ```ts import { getSystemInfo, os, sys } from '@puresnake/snake-ui'; const info = getSystemInfo(); sys(); // getSystemInfo 的便捷入口 os(); // 小写 platform 字符串 ``` ## 状态图标 ```ts import { type2icon } from '@puresnake/snake-ui'; type2icon('success'); // checkmark-circle ``` 支持 `success`、`warning`、`error` 和 `info`,未知值回退到信息图标。 ## API 与平台边界 | 方法 | 返回值与说明 | | ------------------------------- | ----------------------------------------- | | `clipboard(value)` | `Promise`;复制失败时拒绝 | | `toast(title, duration = 2000)` | `void`;调用 `uni.showToast` 的无图标模式 | | `sleep(delay = 0)` | `Promise`;按毫秒等待 | | `getSystemInfo()/sys()` | 实时读取的 uni-app 系统信息 | | `os()` | 系统信息中的 `platform` 小写字符串 | | `type2icon(type)` | 与语义类型对应的图标名 | 剪贴板、提示和系统信息依赖宿主 uni-app API;服务端或普通 Node 环境不能直接调用这些入口。 # 对象转 URL 参数 `queryParams(data)` 把对象拼接成 URL 查询串(与 uview 的 `$u.queryParams` 语义一致);`getQueryParams(url)` 反向把查询串解析为对象。 ```ts import { getQueryParams, queryParams } from '@puresnake/snake-ui'; queryParams({ page: 2, tag: 'new' }); // '?page=2&tag=new' queryParams({ ids: [1, 2] }, false, 'repeat'); // 'ids=1&ids=2' getQueryParams('/pages/search?q=Snake+UI&page=2'); // { q: 'Snake UI', page: '2' } ``` ## 拼接规则(queryParams) `queryParams(data: Record, isPrefix = true, arrayFormat = 'brackets'): string` - 空值(`''` / `undefined` / `null`)参数直接跳过; - 数组按 `arrayFormat` 序列化:`indices`(`ids[0]=1`)、`brackets`(`ids[]=1`,默认)、`repeat`(`ids=1`)、`comma`(`ids=1,2`),非法格式回退 `brackets`; - 普通对象 JSON 序列化并 `encodeURIComponent`; - 其余值经模板字符串原样输出、不做额外编码(与 uview 一致),含中文或特殊字符的值需自行编码后再传入。 ## 解析规则(getQueryParams) `getQueryParams(url: string): Record` 取第一个 `?` 到 `#` 之间的内容。键和值会执行 URL 解码,加号按空格处理;重复键保留最后一个值,无查询串时返回空对象。 该工具按第一个 `=` 拆分参数值,值中再出现未编码的 `=` 会被截断;请先对参数编码。非法百分号编码会抛出 `URIError`。生成跳转参数时使用[路由跳转](/tools/route)。 # 数组乱序 `randomArray(values)` 使用 Fisher–Yates 算法返回乱序副本,不修改原数组。 ```ts import { randomArray } from '@puresnake/snake-ui'; const source = [1, 2, 3, 4]; const result = randomArray(source); // source 仍为 [1, 2, 3, 4] ``` ## API 与边界 `randomArray(values: readonly T[]): T[]` 接受只读数组并返回新数组,元素对象本身仍是原引用;空数组返回空数组。适合随机展示非敏感的推荐项或题目顺序。 底层随机数来自 `Math.random()`。随机顺序不适合密码学、抽奖或可审计场景;需要可复现顺序时也应使用业务指定的随机种子方案。 # 随机数值 `random(min = 0, max = 1)` 返回包含上下界的随机整数。参数顺序可以互换,小数边界会向有效整数范围收缩。 ```ts import { random } from '@puresnake/snake-ui'; random(1, 6); // 1 到 6 random(10, 5); // 5 到 10 ``` ## API 与边界 `random(min = 0, max = 1): number` 返回闭区间内的整数;`random()` 因而返回 0 或 1。小数下界向上取整、上界向下取整,调用方应提供至少包含一个整数的区间。 底层使用 `Math.random()`,不适合安全令牌、密码学或公平性要求高的抽奖。打乱列表可使用[数组乱序](/tools/random-array)。 # 路由跳转 `route()` 提供强类型、Promise 化的 uni-app 页面导航;`navTo()` 保留旧项目的同步调用与 tabBar 降级行为。 ## 基础使用 ```ts import { route } from '@puresnake/snake-ui'; await route('/pages/goods/detail', { id: 1, source: 'home' }); await route({ type: 'redirectTo', url: '/pages/login' }); ``` ## 导航类型 | type | uni-app API | 是否需要 URL | | ------------------------ | ------------------ | ------------ | | `navigateTo`、`to` | `uni.navigateTo` | 是 | | `redirect`、`redirectTo` | `uni.redirectTo` | 是 | | `switchTab`、`tab` | `uni.switchTab` | 是 | | `reLaunch` | `uni.reLaunch` | 是 | | `navigateBack`、`back` | `uni.navigateBack` | 否 | ```ts await route({ type: 'back', delta: 2 }); ``` `delta` 默认为 1,输入会取整且最小为 1。`animationType` 和 `animationDuration` 仅在 `navigateTo`、`redirectTo` 时透传,具体动画效果由目标平台决定。 ## 参数编码 字符串、数字和布尔值会写入 query;`null` 与 `undefined` 被忽略;数组使用重复键;已有 query 与 hash 会被保留。 ```ts await route('/pages/search#result', { keyword: 'Snake UI', page: 2, tag: ['new', 'hot'] }); // /pages/search?keyword=Snake%20UI&page=2&tag=new&tag=hot#result ``` `switchTab` 不携带 `params`,避免不同小程序平台产生不一致行为。 ## route 与 navTo - 新代码使用 `route()`,导航失败时 Promise 会拒绝。 - 已有组件可继续使用 `navTo()`;它在 `navigateTo` 失败后尝试 `switchTab`。 - `route()` 不处理任意 H5 外链或小程序跳转,这些策略应由业务 link service 统一负责。 ## API 与失败处理 `route(url, params?)` 和 `route(options)` 都返回 `Promise`。缺少 URL、导航类型不支持、平台 API 不可用或跳转失败时,Promise 会拒绝;调用方应在关键导航处处理失败。 `navTo(url?)` 返回 `void`,还识别 H5 HTTP 外链、`/miniprogram` 和 `/serviceChat` 等旧业务协议。其特殊协议由运行平台及宿主 API 决定,错误无法通过 Promise 捕获;新业务应明确采用自己的链接策略。 # 样式与单位 这组工具统一处理 uni-app 尺寸和行内样式。 ## 单位补全 ```ts import { addUnit } from '@puresnake/snake-ui'; addUnit(24); // 24rpx addUnit('1rem'); // 1rem addUnit('12 24px'); // 12rpx 24px ``` ## 样式转换 ```ts import { addStyle, kebabCase, toStyle } from '@puresnake/snake-ui'; kebabCase('backgroundColor'); // background-color addStyle('color:red;font-size:12px'); toStyle({ backgroundColor: '#fff' }, 'color:#222'); // background-color:#fff;color:#222 ``` `toStyle` 后传入的声明覆盖同名属性;null、undefined 和空字符串不会写入结果。 ## API 与边界 | 方法 | 行为 | | ------------------------------------ | ------------------------------------------------------ | | `addUnit(value = 0, unit = 'rpx')` | 给裸数字追加单位,含多值简写;空值返回 `0rpx` | | `kebabCase(name)` | 将驼峰、空格或下划线写法转换为 CSS 短横线写法 | | `addStyle(style, target = 'object')` | 将声明串转为样式对象;`target = 'string'` 时返回字符串 | | `toStyle(...styles)` | 合并样式对象或声明串,返回 CSS 声明串 | `addUnit` 只补全单位,不做 px 与 rpx 的比例换算。请按 uni-app 尺寸体系传入值;涉及页面宽度的换算要先确认设备视口。 # 规则校验 `test` 提供常用的轻量类型与格式判断。 ```ts import { test } from '@puresnake/snake-ui'; test.email('dev@example.com'); test.mobile('13800138000'); test.url('https://snake.example.com'); test.number('12.5'); test.string('Snake'); test.object({ name: 'Snake' }); test.array([]); test.empty({}); ``` | 方法 | 判断内容 | | --------------------- | ------------------------------ | | `email` | 常见邮箱结构 | | `mobile` | 中国大陆手机号段格式 | | `url` | HTTP/HTTPS URL | | `number` | 可转换且有限的数字 | | `string/object/array` | 基础类型 | | `empty` | null、空字符串、空数组或空对象 | ## 其他常用方法 | 方法 | 判断内容 | | ---------------------------- | --------------------------------------------- | | `date/dateISO` | 可解析日期、`yyyy/mm/dd` 或 `yyyy-mm-dd` 形式 | | `digits/amount` | 纯数字、最多两位小数的金额格式 | | `idCard/carNo` | 大陆身份证号码格式、车牌号码格式 | | `contains/range/rangeLength` | 包含指定内容、数值区间、字符串长度区间 | | `jsonString` | 可解析为对象或数组的 JSON 字符串 | | `code(value, len = 6)` | 固定长度的数字验证码 | | `image/video` | 常见图片或视频文件扩展名 | | `func/promise/regExp` | 函数、Promise 形对象、正则对象 | 所有方法返回布尔值;`empty` 的别名为 `isEmpty`。这些规则适合前端即时反馈,部分格式判断只检查形状,不能代替服务端校验或安全验证。 # 时间格式化 Snake UI 提供绝对时间格式化和相对时间描述。`timeFormat` 是 `formatTime` 的兼容别名。 ## 绝对时间 ```ts import { formatTime, timeFormat } from '@puresnake/snake-ui'; formatTime(Date.now(), 'yyyy-mm-dd hh:MM:ss'); timeFormat(new Date(), 'yyyy/mm/dd'); ``` | 令牌 | 含义 | | ------ | -------- | | `yyyy` | 四位年份 | | `mm` | 两位月份 | | `dd` | 两位日期 | | `hh` | 两位小时 | | `MM` | 两位分钟 | | `ss` | 两位秒 | ## 相对时间 ```ts import { timeFrom } from '@puresnake/snake-ui'; timeFrom(Date.now() - 5 * 60 * 1000); // 5分钟前 ``` `timeFrom()` 接受 `Date`、日期字符串、秒级或毫秒级时间戳。无效时间返回空字符串;未来时间返回“刚刚”;超过 30 天返回 `yyyy-mm-dd`。 ## 参数与边界 | 方法 | 参数 | 返回值 | | ----------------------------- | -------------------------------------- | ---------------------------------- | | `formatTime(value, pattern?)` | 日期值;默认模板 `yyyy-mm-dd hh:MM:ss` | 格式化字符串,非法日期返回空字符串 | | `timeFormat(value, pattern?)` | `formatTime` 的兼容别名 | 同上 | | `timeFrom(value, now?)` | 日期值;`now` 可注入当前毫秒时间戳 | 相对时间或日期字符串 | `formatTime` 对 10 位数字按秒级时间戳处理,`timeFrom` 对绝对值小于 `1e12` 的数字按秒处理。令牌中的月份 `mm` 与分钟 `MM` 区分大小写;输出使用运行环境的本地时区。 # 去除空格 `trim(value, position = 'both')` 按指定位置移除空白。 ```ts import { trim } from '@puresnake/snake-ui'; trim(' Snake UI '); // 'Snake UI' trim(' Snake', 'left'); // 'Snake' trim('Snake ', 'right'); // 'Snake' trim('Snake UI', 'all'); // 'SnakeUI' ``` ## API 与使用场景 `trim(value: string, position: 'both' | 'left' | 'right' | 'all' = 'both'): string` 返回处理后的新字符串。`both` 只去除首尾空白,`all` 删除整串中的空白,包括换行和制表符;需要保留词间空格时不要选 `all`。 它适合表单输入的轻量整理。请先确认输入是字符串;金额、号码等领域格式仍应交给专门校验器,参见[规则校验](/tools/test)。 # 颜色管理 `useColor()` 提供当前主题色板和局部颜色覆盖入口。 ```vue ``` ## 返回值与作用范围 | 成员 | 用途 | | ----------------- | ------------------------------------------------------- | | `color` | 当前主题的共享响应式色板,可读取 `color.primary` 等颜色 | | `setColor(patch)` | 覆盖当前主题的部分颜色并更新对应 CSS 变量 | `color` 是共享状态,修改会影响使用 Snake CSS 变量的组件;它不是仅作用于调用组件的局部样式。临时的单组件颜色应优先使用组件 Props。主题切换和暗色模式见[主题管理](/tools/use-theme)。 # 多语言 Snake UI 内置简体中文 `zh-CN` 和英文 `en-US`。语言状态是响应式的,切换结果会通过 `uni.setStorageSync` 保存,刷新或跳转页面后仍会沿用上次选择。 ## 初始化语言 安装插件时可指定默认语言: ```ts import SnakeUI from '@puresnake/snake-ui'; app.use(SnakeUI, { locale: { defaultLocale: 'zh-CN' } }); ``` 如果本地已经保存过用户选择,保存值优先于 `defaultLocale`。 ## 在组件中切换 `useLocale(namespace?)` 提供当前语言、可选语言、翻译函数和切换方法: ```vue ``` 也可以在组件外直接切换: ```ts import { setLocale } from '@puresnake/snake-ui'; setLocale('en-US'); ``` 传入未注册的语言时,`setLocale()` 返回 `false`,并保持当前语言不变。 ## 翻译和插值 直接使用 `translate()`,或者通过 `useLocale()` 获取 `t()`: ```ts import { translate, useLocale } from '@puresnake/snake-ui'; translate('common.confirm'); // 当前为 en-US 时返回 Confirm const { t } = useLocale('checkout'); t('welcome', { name: 'Snake' }); // 读取 checkout.welcome,并替换 {name} ``` `t()` 支持对象插值和数组插值。设置 namespace 后,调用时只需传入命名空间内部的 key。 ## 自定义或覆盖语言包 通过插件配置追加语言,也可以局部覆盖内置语言。相同语言名称会与内置词条深度合并: ```ts app.use(SnakeUI, { locale: { defaultLocale: 'en-US', locales: [ { name: 'en-US', label: 'English', messages: { checkout: { submit: 'Place order', welcome: 'Hello, {name}' } } }, { name: 'ja-JP', label: '日本語', messages: { common: { confirm: '確認' } } } ] } }); ``` ## 缺失词条回退 翻译按以下顺序查找: 1. 当前语言。 2. 内置或自定义覆盖后的简体中文 `zh-CN`。 3. 原始 key。 因此英文包缺少 `checkout.submit` 时会显示中文词条;中文也缺少时会直接显示 `checkout.submit`,不会渲染空文本。 语言和主题可以在右侧手机预览中直接切换。应用级接入、语言包组织和业务国际化协同方式见[国际化指南](/guide/internationalization),完整插件配置参见[全局配置总览](/guide/foundation)。 ## API 速查 `useLocale(namespace?)` 返回 `currentLocale`、`locales`、`t`、`initLocales` 和 `setLocale`。`t(key, replacements?, locale?)` 返回翻译字符串;传入命名空间后,`key` 相对于该命名空间。`setLocale(name)` 返回布尔值,表示切换是否成功。 `currentLocale` 与 `locales` 是响应式状态。仅需在组件外查询文案时可以使用 `translate(key, replacements?, locale?)`;应用启动阶段的初始化与覆盖策略以[国际化指南](/guide/internationalization)为准。 # useModal `useModal()` 提供 modal 的函数式调用,返回 `{ show, confirm, close, clearLoading }`。使用前需在页面或应用里至少存在一个 `` 或 `` 实例用于承接事件,不影响原 `` 声明式用法。 ```vue ``` ```vue ``` ## 调用方式 - 应用级:`useModal()` / `useModal(true)` / `useModal({ global: true })`,配合 ``。 - 页面级:`useModal(false)` / `useModal({ page: true })` / `useModal({ page: 'pageId' })`,配合 `` 或 ``。 ## API | 方法 | 说明 | | --------------------------- | ---------------------------------------------------------- | | `show(contentOrOptions)` | 显示 modal;传入字符串时作为 `content` | | `confirm(contentOrOptions)` | 显示带确认/取消按钮的 modal,默认 `showCancelButton: true` | | `close()` | 关闭 modal | | `clearLoading()` | 清除确认按钮 loading 状态(异步关闭场景) | `contentOrOptions` 与 `` 的 props 一一对应(除 `modelValue`),并额外支持 `onConfirm` / `onCancel` 回调。 `confirm()` 默认显示确认和取消按钮;四个方法均返回 `void`,不会等待用户选择。异步确认时,业务应在成功后调用 `close()`;若请求失败并需要恢复确认按钮状态,可调用 `clearLoading()`。 页面级和全局实例的作用域需与 `useModal` 的调用模式一致。 # useDebounce 与 useThrottle 两个组合式入口分别返回可取消的防抖和节流函数。 ```vue ``` ## API 与清理 `useDebounce(callback, wait = 300)` 和 `useThrottle(callback, wait = 300)` 分别返回带 `cancel()` 的函数。两者都透传回调参数并返回 `void`;`useDebounce` 不提供底层 `debounce` 的 `immediate` 参数。 组合式函数不会自动在卸载时取消,调用方仍需显式清理。节流等待窗口内的执行时机与示例见[节流与防抖](/tools/debounce-throttle)。 # useRect `useRect(selector?, all?)` 返回响应式的节点信息:`rect`、`getRect()` 和 `refresh()`。 ```vue ``` ## 返回值与边界 `useRect(selector?, all = false)` 返回响应式 `rect`,以及 `getRect(selector?, delay = 0)`、`refresh(selector?, delay?)`。两种方法都会等待 Vue 下一轮 DOM 更新,再按可选毫秒延迟查询;查询结果写入 `rect.value` 并作为 Promise 结果返回。 未提供选择器时直接返回当前 `rect.value`;查询没有匹配项时可能得到 `null` 或空数组,调用方应按实际结果处理。`all: true` 使用 `selectAll`。只需一次性查询且希望得到零值兜底对象时,使用[节点布局信息](/tools/get-rect)。 # useRouter `useRouter()` 在组合式代码中同时提供新的 Promise 路由和旧的兼容路由。 ```vue ``` ## 返回值与选择 `useRouter()` 返回 `{ route, navTo }`,与按需导入的同名函数共享实现。`route` 返回 Promise,导航失败时可用 `try/catch` 处理;`navTo` 返回 `void`,保留旧项目的特殊链接处理与 `navigateTo → switchTab` 降级。 新代码优先使用 `route`。两种入口的参数、特殊链接与平台行为见[路由跳转](/tools/route)。 # 主题管理 `useTheme()` 在 Vue 组件中提供响应式主题、暗色模式、颜色和 CSS 变量。 ```vue ``` ## 切换主题 ```vue ``` ## 返回值与状态 `currentTheme`、`themes`、`darkMode`、`color`、`cssVars` 和 `themeStyle` 是响应式状态;`themeStyle` 是 CSS 变量对象的计算值。`initTheme` 用于初始化,`setTheme`、`setThemeColor`、`setDarkMode`、`toggleDarkMode` 与 `isInDarkMode` 用于切换或读取模式。 主题是应用级共享状态。主题注册、系统跟随和持久化策略见[多主题与暗黑模式](/guide/multi-theme),仅调整当前色板见[颜色管理](/tools/use-color)。 # useToast `useToast()` 提供函数式消息提示,依赖页面/应用根部挂载的 ``(或页面级 ``)承接事件。 ## 快速开始 应用根部(如 `App.vue` / 布局组件)挂载全局 toast: ```vue ``` 业务中调用: ```vue ``` `show(titleOrOptions)` 既可传字符串,也可传配置对象: ```ts toast.show({ title: '受价格波动影响,订单将自动终止', icon: false, // 不显示图标 position: 'bottom', // center / top / bottom duration: 3000 // ms;0 表示常驻,省略时使用组件默认值 2000 }); ``` ## API | 方法 | 说明 | | -------------------------------------------- | ------------------------ | | `show(titleOrOptions)` | 显示默认样式 toast | | `success/error/warning/info(titleOrOptions)` | 显示对应类型 toast | | `loading(titleOrOptions)` | 显示加载动画(默认常驻) | | `close()` | 关闭 toast | 四个提示类型方法和 `show()` 都返回 `void`,不能 `await` 提示消失。`loading()` 未指定 `duration` 时会显式设为 0;完成异步任务后应调用 `close()`。需要固定展示时长的普通提示,传入正数毫秒值。 ## 模式 - `useToast()` / `useToast(true)` / `useToast({ global: true })` — 应用级(需 ``) - `useToast(false)` / `useToast({ page: true })` — 页面级(需 ``) - `useToast({ page: 'pageId' })` — 指定页面的 `` ## 声明式 ref 调用 也可通过 ref 直接调用组件方法: ```vue ``` `ref` 只有在组件挂载后才有值,应在事件处理或挂载后调用。只需短暂的无图标提示时,也可使用[平台辅助](/tools/platform)中的 `toast()`。