开发指南
一、快速上手
演示
使用微信扫描下方的小程序码,在线查看组件的渲染效果。
注:如果因为网络等原因,小程序码图片无法加载,也可以直接输入 Meleon Uni-ui
关键字查询

安装
# npm
npm install @meleon/uni-ui
引入
H5 端
import MeleonUI from "@meleon/uni-ui"
export function createApp() {
const app = createSSRApp(App)
app.use(MeleonUI)
return { app }
}
微信小程序端
对比分别在项目入口文件 main.ts 和组件库的入口文件 meleon-ui.ts 里注册的组件,被编译到微信小程序上的结果:
// main.ts
import { createSSRApp } from 'vue'
import MeleonUI from "@meleon/uni-ui";
import MlButton from '@meleon/uni-ui/lib/ml-button/index.vue'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
app.use(MeleonUI)
app.component('MlButtonGlobal', MlButton)
return {
app
}
}
// meleon-ui.ts
import type { App, Plugin } from 'vue'
import MlButton from './ml-button'
const components: Record<string, Plugin> = {
MlButton,
}
const install = (app: App) => {
for (const key in components) {
if (Object.prototype.hasOwnProperty.call(components, key)) {
app.use(components[key])
}
}
}
const MeleonUI = { install }
export default MeleonUI
// ml-button/index.ts
import type { App } from 'vue'
import _Button from './index.vue'
const install = async (app: App) => {
app.component('MlButton', _Button)
}
export default { install }
虽然本质上都是使用 app.component
实现注册组件,但 uniapp 编译的结果却并不完全相同
在 main.ts
中注册 MlButtonGroup
组件被编译成函数
而 meleon-ui.ts
里的组件被编译成对象
在使用时也是前者可以被正常渲染成组件展示到页面上
因此,如果希望在微信小程序端实现批量注册组件,需要使用 uniapp 提供的 easycom
方法
详细内容可跳转:https://uniapp.dcloud.net.cn/collocation/pages.html#easycom
// page.json
{
"easycom": {
"custom": {
"^ml-(.*)": "@meleon/uni-ui/lib/ml-$1/index.vue"
}
}
}
二、定制主题
MeleonUI 为用户提供了自定义主题的方法,可以通过向 ml-config-provider
组件传入 themes
属性,同时修改当前页面所有 ml- 组件的主题色
<!-- template -->
<ml-config-provider :themes="themes">
<!-- 消息提示 -->
<ml-message ref="messageRef" />
<!-- 导航栏 -->
<ml-navigator
:title="$t('home.navigation.title')"
title-color="#FFFFFF"
background="#7A98B3"
></ml-navigator>
<ml-button
type="primary"
@click="onNavigate('/pages/componentList/index')"
>
{{ $t('home.actions.start') }}
<ml-icon icon="ml-arrow-right--line" color="#FFFFFF" />
</ml-button>
</ml-config-provider>
// script
import type { ConfigProviderProps } from '@meleon/uni-ui'
const themes: ConfigProviderProps['themes'] = {
primary: '#D74B4B',
}
themes 支持以下属性,可根据项目的设计风格批量修改,当然,直接通过 CSS 修改样式也是可以的。
export type ColorType = 'primary' | 'info' | 'success' | 'warning' | 'danger'
三、类型声明
在使用组件时,为了得到更好的类型提示,可以在 tsconfig.json
中注入 MeleonUI
的类型声明文件,如下所示。
如果你的编辑器中安装了 Volar
插件,注入成功后应该可以看到组件标签的颜色发生了变化,且当尝试传入组件 props 时,编辑器也会给出可选值的提示信息。
{
"types": ["@dcloudio/types", "@meleon/uni-ui"]
}
四、更新日志
- 1.2.0
- refactor: 打包结果调整
- 去除初始的 .ts 文件
- 去除用于 重新导出 的
index.js
和 index.d.ts
文件 - 使用 terser 压缩代码,大幅降低组件库构建到小程序后的体积
@meleon/uni-ui
小程序主包的构建体积从优化前的 2.2MB 降低到现在的 958KB- 注:如果准备将
1.1
版本升级到 1.2
版本,最好检查下之前对组件库内部方法、类型的引用路径是否存在问题,避免出现 bug
- feat: 调整
ml-form
组件,添加下拉选框、多选、日期选择器、开关等表单项
- 1.1.13
- feat: 新增
ml-form
组件【暂时仅支持 input 组件作为表单项】 - feat: 新增
ml-transition
组件
- 1.1.12
- style:
ml-drawer
组件添加动效 - fix:
ml-list
组件修改虚拟列表插槽名称错误 - feat: 新增
ml-datetime-picker
、ml-time-picker
两个时间选择组件
- 1.1.11
- feat: 调整
ml-navigator
组件的结构,完善功能 - feat: 添加
ml-switch
组件 - feat:
ml-cell
组件添加 SWITCH
类型 - fix:
ml-cell
组件传入的 value 发生变化时未触发页面更新 - feat: 新增
ml-list
组件,初步支持基础列表和虚拟列表功能
- 1.1.10
- fix:
ml-checkbox
设置 direction 失效的问题 - fix:
ml-image
预览层层级过低的问题 - fix:
ml-select
无激活样式的问题 - fix:
ml-input-tag
确认后未触发新增标签 - docs:
@meleon/uni-ui
上线微信小程序,可体验各个组件的使用效果【微信扫描“演示”小程序码】
- 1.1.9
- fix:
ml-loading
图标缺失,ml-button
组件设置 loading 不生效 - feat: 新增
ml-image
组件 - feat:
ml-tree
组件模块拆分,支持自定义 title 节点 - feat: 新增
ml-icon-switcher
小组件 - fix:
ml-button
单图标按钮图标偏移的问题 - feat:
ml-tree
组件基本功能完善,支持文本选中、复选框选择、自定义标题节点等 - fix: 去除
ml-checkbox
组件无文本时样式的偏移 - feat:
ml-tree
组件新增对外暴露的 expand、check 及 select 等方法
- 1.1.8
- feat: 新增
ml-cell
、ml-cell-group
组件 - feat: 新增
ml-uploader
组件
- 1.1.7
- feat: 新增
ml-config-provider
组件 - docs: 调整项目接口,补全TS类型,新增 README 文档
组件
头像 Avatar
基本使用
如果头像内容是文字的话,会自动调节字体大小,来适应头像框
<!-- 基础使用 -->
<ml-avatar>Meleon</ml-avatar>
<!-- 设置尺寸 -->
<ml-avatar :size="36">Meleon</ml-avatar>
<!-- 设置形状 -->
<ml-avatar :size="28" shape="circle">Meleon</ml-avatar>
<!-- 插入图片 -->
<ml-avatar shape="circle">
<image src="@/assets/home/avatar.png" mode="widthFix" />
</ml-avatar>
APIs
prop | type | default |
---|
size | number | 32 |
shape | square | circle | square |
Slots
name | desc |
---|
default | 默认插槽,传递文本或图片 |
头像组 AvatarGroup
基本使用
除了 maxCount 等属性,还可以传入 Avatar 的 size、shape 等属性实现批量设置
<ml-avatar-group :size="36" :offset="10" shape="circle">
<ml-avatar>Meleon</ml-avatar>
<ml-avatar>Aliee</ml-avatar>
<ml-avatar>Bob</ml-avatar>
</ml-avatar-group>
APIs
prop | type | default | desc |
---|
maxCount | number | 3 | 多出的部分会显示剩余的 count |
offset | number | 0 | 头像组件之前的偏移量 |
size | number | 32 | 头像组件的尺寸 |
shape | square | circle | square | 头像组件的形状 |
按钮 Button
基本使用
<ml-button
type="primary"
size="mini"
status="success"
>
Primary
</ml-button>
<ml-button
type="secondary"
size="mini"
shape="round"
status="success"
>
Secondary
</ml-button>
<ml-button
type="outline"
size="mini"
status="success"
>
Outline
</ml-button>
<ml-button
type="text"
size="mini"
status="success"
@click="handleClick"
>
Text
</ml-button>
APIs
prop | type | desc |
---|
type | primary | secondary | outline | text | 按钮类型 |
size | mini | small | medium | large | 按钮尺寸 |
shape | square | round | circle | 按钮形状 |
status | normal | success | warning | danger | 按钮状态 |
loading | boolean | 是否加载中 |
disabled | boolean | 是否禁用 |
Slots
name | desc |
---|
default | 默认插槽 |
icon | 图标插槽【位于默认插槽左侧】 |
Emits
单元格 Cell
基本使用
<ml-cell-group title="测试分组" style="width: 100%">
<ml-cell
:type="CellTypeEnum.TEXT"
label="测试标题"
value="测试内容"
description="测试描述"
disabled
allow-edit
style="width: 100%"
@change="handleCellChange"
></ml-cell>
<ml-cell
:type="CellTypeEnum.BUTTON"
label="测试按钮"
btn-status="danger"
disabled
style="width: 100%"
@btn-click="handleClick"
></ml-cell>
<ml-cell
:type="CellTypeEnum.NAV"
label="测试回到首页"
value="回首页"
url="/pages/home/index"
:disabled="false"
style="width: 100%"
>
<template #rightIcon>
<ml-icon name="ml-arrow-right--line" color="var(--info-color-7)"></ml-icon>
</template>
<template #value>
<text style="font-size: 14px; color: var(--info-color-7)">通过插槽展示内容</text>
</template>
</ml-cell>
</ml-cell-group>
APIs
prop | type | default | desc |
---|
label | string | '' | 左侧标题 |
description | string | '' | 左侧描述 |
value | string | '' | 右侧 值 |
type | text | button | navigator | text | 单元格类型【推荐使用 CellTypeEnum 枚举变量赋值】 |
disabled | boolean | false | 是否禁用 |
allowEdit | boolean | false | 文本单元格是否允许修改 |
btnStatus | normal | success | warning | danger | normal | 按钮单元格的按钮类型 |
url | string | '' | 导航单元格的跳转地址【小程序页面地址需要保留前面的 / 字符】 |
Slots
name | desc |
---|
label | 左侧标题插槽【会覆盖默认的 label 和 description 区域】 |
value | 右侧内容插槽 |
rightIcon | 导航单元格生效【覆盖右侧图标】 |
Emits
name | desc |
---|
change | 文本单元格修改内容后触发 |
btnClick | 按钮单元格点击触发 |
navigate | 导航单元格点击跳转后触发【暂不暴露,考虑有没有必要放出来】 |
CellGroup APIs
prop | type | default | desc |
---|
title | string | '' | 分组名称 |
CellGroup Slots
name | desc |
---|
title | 标题插槽【覆盖标题内容】 |
选择框 Checkbox
基本使用
<ml-checkbox v-model:checked="checked1">Radio</ml-checkbox>
<ml-checkbox indeterminate>Radio</ml-checkbox>
<ml-checkbox v-model:checked="checked1" disabled>Radio</ml-checkbox>
APIs
props | type | default | desc |
---|
checked | boolean | false | 是否选中 |
indeterminate | boolean | false | 是否为半选状态 |
disabled | boolean | false | 是否禁用 |
value | string | number | '' | CheckboxGroup 下的 value 标识 |
Slots
Emits
event | desc |
---|
update:checked | 切换事件 |
选择框分组 CheckboxGroup
基本使用
<ml-checkbox-group
v-model:checked-list="checked3"
mode="multi"
:max="3"
:min="1"
>
<ml-checkbox value="A">RadioA</ml-checkbox>
<ml-checkbox value="B">RadioB</ml-checkbox>
<ml-checkbox value="C">RadioC</ml-checkbox>
<ml-checkbox value="D">RadioD</ml-checkbox>
<ml-checkbox value="E">RadioE</ml-checkbox>
</ml-checkbox-group>
APIs
prop | type | default | desc |
---|
checkedList | Array<string | number> | 必填 | 选中的选项列表 |
min | number | 0 | 至少选中数量 |
max | max | Infinity | 至多选中数量 |
direction | vertical | horizontal | horizontal | 纵向或横向排列 |
mode | single | multi | single | 切换单选或多选 |
Emits
event | desc |
---|
update:checkedList | 更新选中的列表 |
全局配置 ConfigProvider
基本使用
设置全局主题色
<ml-config-provider :themes="themes">
<ml-button type="primary"></ml-button>
<ml-button type="success"></ml-button>
<ml-button type="warning"></ml-button>
<ml-button type="danger"></ml-button>
</ml-config-provider>
import type { ConfigProviderProps } from '~/lib/ml-config-provider/index.interface'
const themes: ConfigProviderProps['themes'] = {
primary: '#D74B4B'
}
APIs
prop | type | example |
---|
themes | ConfigProviderProps'themes' | { primary: '#D74B4B' } |
数值显示 CountTo
基本使用
<ml-count-to
:from="0"
:to="1250.44"
animation
:animation-duration="5000"
:value-style="{ color: '#0fbf60' }"
>
<template #suffix>
<text>%</text>
</template>
</ml-count-to>
APIs
prop | type | default | desc |
---|
from | number | 0 | 起始值 |
to | number | required | 结束时展示的数据,必填 |
animation | boolean | false | 是否开启动画 |
animationDuration | number | 1000 | 动画持续时间 |
showSeperator | boolean | false | 是否显示千分位分隔符 |
valueStyle | Record<string, any> | {} | 数据的样式 |
Slots
name | desc |
---|
prefix | 数值左侧的内容 |
suffix | 数值右侧的内容 |
Expose
name | desc |
---|
start | 开启动画 |
pause | 暂停动画 |
restart | 继续动画 |
时间选择器 DatetimePicker
基本使用
<ml-datetime-picker
v-model="value"
mode="date"
:disabled-date="isDateDisabled"
style="width: 100%"
@change="handleValueChange"
>
<template #trigger>
<ml-cell
label="日期选择器"
:value="formatToDateTime(value)"
style="width: 100%"
></ml-cell>
</template>
</ml-datetime-picker>
const value = ref(new Date())
const isDateDisabled = (current: Date) => {
return current.getTime() < new Date().getTime() - 24 * 60 * 60 * 1000
}
const handleValueChange = (value: DatetimePickerProps['modelValue']) => {
console.log('change', value)
}
APIs
prop | type | default | desc |
---|
modelValue | Date, string, number | '' | 选择的日期时间 |
defaultModelValue | Date, string, number | '' | 默认展示的日期时间 |
pickerValue | Date, string, number | '' | 面板头部展示的时间 |
defaultPickerValue | Date, string, number | '' | 面板头部默认展示的时间 |
| | | |
locale | Record<string, any> | {} | 自定义面板中展示的文本 |
mode | 'date', 'year', 'month' | 'date' | 选择器模式 |
format | string | 'YYYY-MM-DD' | 时间转换格式 |
| | | |
disabledDate | (current: Date) => boolean | undefined | 判断日期是否禁用 |
Emits
name | type | desc |
---|
change | (value: Date) => void | 选中值发生变化时触发 |
update:modelValue | (value: Date) => void | 双向绑定选中日期 |
抽屉 Drawer
基本使用
<ml-drawer
v-model:visible="modelVisible"
:placement="placement"
:has-nav="hasNav"
>
<template #title>自定义标题</template>
<text>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni, dolor libero
blanditiis distinctio commodi totam recusandae aliquam fugit officiis sequi
perspiciatis non animi, eaque facilis sed reiciendis in aut vel.
</text>
<template #footer>
<ml-button>自定义页脚</ml-button>
</template>
</ml-drawer>
APIs
prop | type | default | desc |
---|
hasNav | boolean | true | 当前页面有无导航栏,以控制 drawer 高度 |
visible | boolean | required | 是否显示 |
placement | left | right | top | bottom | right | 展开的方向 |
width | number | 250 | placement 为 left | right 时,抽屉的宽度 |
height | number | 250 | placement 为 top | bottom 时,抽屉的高度 |
radius | number | 0 | 抽屉圆角 |
okText | string | 确定 | 底部确认按钮的文本 |
cancelText | string | 取消 | 底部取消按钮的文本 |
Slots
name | desc |
---|
default | 主体内容 |
title | 标题内容 |
footer | 底部内容 |
Emits
name | desc |
---|
update:visible | 显示状态变化触发 |
close | 点击取消按钮 |
ok | 点击确认按钮 |
图标 Icon
基本使用
<ml-icon :name="icon" :size="24" color="#808080" />
export default {
id: '4118979',
name: 'MeleonUI',
font_family: 'ml-icon',
css_prefix_text: 'ml-',
description: '',
glyphs: [
{
icon_id: '8106223',
name: 'cancel',
font_class: 'close--circle',
unicode: 'e698',
unicode_decimal: 59032
},
{
icon_id: '8106241',
name: 'information',
font_class: 'info--circle',
unicode: 'e6a5',
unicode_decimal: 59045
},
{
icon_id: '8106248',
name: 'selection',
font_class: 'selection--circle',
unicode: 'e6a6',
unicode_decimal: 59046
},
{
icon_id: '11992738',
name: 'github',
font_class: 'github',
unicode: 'e6a9',
unicode_decimal: 59049
},
{
icon_id: '18531280',
name: 'right arrow',
font_class: 'arrow-right--line',
unicode: 'e701',
unicode_decimal: 59137
},
{
icon_id: '38175316',
name: 'right arrow',
font_class: 'arrow-left--line',
unicode: 'e87f',
unicode_decimal: 59519
},
{
icon_id: '12865674',
name: 'night',
font_class: 'night',
unicode: 'e6ef',
unicode_decimal: 59119
},
{
icon_id: '12865690',
name: 'day',
font_class: 'day',
unicode: 'e6f1',
unicode_decimal: 59121
},
{
icon_id: '702307',
name: 'drag',
font_class: 'drag',
unicode: 'e7d0',
unicode_decimal: 59344
},
{
icon_id: '11488125',
name: 'seleted',
font_class: 'selected',
unicode: 'e763',
unicode_decimal: 59235
},
{
icon_id: '10678428',
name: 'mirror light ctrl',
font_class: 'filter',
unicode: 'e6e0',
unicode_decimal: 59104
},
{
icon_id: '5772874',
name: '复制',
font_class: 'copy',
unicode: 'e617',
unicode_decimal: 58903
},
{
icon_id: '4936963',
name: 'CodeSandbox',
font_class: 'code-sandbox',
unicode: 'e87e',
unicode_decimal: 59518
},
{
icon_id: '8106210',
name: 'bluetoothon',
font_class: 'bluetoothon',
unicode: 'e697',
unicode_decimal: 59031
},
{
icon_id: '8106293',
name: 'wifi',
font_class: 'wifi',
unicode: 'e6a4',
unicode_decimal: 59044
},
{
icon_id: '10678426',
name: 'message',
font_class: 'message',
unicode: 'e6df',
unicode_decimal: 59103
},
{
icon_id: '10678434',
name: 'search',
font_class: 'search',
unicode: 'e6e1',
unicode_decimal: 59105
},
{
icon_id: '10678439',
name: 'scan QR',
font_class: 'scan',
unicode: 'e6e2',
unicode_decimal: 59106
},
{
icon_id: '10678401',
name: 'back',
font_class: 'arrow-left',
unicode: 'e6db',
unicode_decimal: 59099
},
{
icon_id: '8106272',
name: 'next',
font_class: 'arrow-right',
unicode: 'e6a3',
unicode_decimal: 59043
},
{
icon_id: '8106251',
name: 'increase',
font_class: 'plus',
unicode: 'e69f',
unicode_decimal: 59039
},
{
icon_id: '8106217',
name: 'delete',
font_class: 'delete',
unicode: 'e699',
unicode_decimal: 59033
},
{
icon_id: '8106245',
name: 'close',
font_class: 'close',
unicode: 'e69e',
unicode_decimal: 59038
},
{
icon_id: '10670577',
name: 'address',
font_class: 'address',
unicode: 'e6a7',
unicode_decimal: 59047
},
{
icon_id: '12865660',
name: 'connect device',
font_class: 'connect',
unicode: 'e6e7',
unicode_decimal: 59111
},
{
icon_id: '12865665',
name: 'done work',
font_class: 'donework',
unicode: 'e6e9',
unicode_decimal: 59113
},
{
icon_id: '12865672',
name: 'like',
font_class: 'like',
unicode: 'e6eb',
unicode_decimal: 59115
},
{
icon_id: '12865673',
name: 'mark',
font_class: 'mark',
unicode: 'e6ec',
unicode_decimal: 59116
},
{
icon_id: '12865685',
name: 'share',
font_class: 'share',
unicode: 'e6ee',
unicode_decimal: 59118
},
{
icon_id: '12865693',
name: 'setting',
font_class: 'setting',
unicode: 'e6f0',
unicode_decimal: 59120
},
{
icon_id: '8106224',
name: 'down',
font_class: 'arrow-down',
unicode: 'e69b',
unicode_decimal: 59035
},
{
icon_id: '8106260',
name: 'upward',
font_class: 'arrow-up',
unicode: 'e6a1',
unicode_decimal: 59041
},
{
icon_id: '8106276',
name: 'visible',
font_class: 'eye-close',
unicode: 'e6a2',
unicode_decimal: 59042
},
{
icon_id: '8106285',
name: 'eye_protection',
font_class: 'eye',
unicode: 'e6a0',
unicode_decimal: 59040
}
]
}
图片 Image
基本使用
prop | type | default | desc |
---|
hasNav | boolean | true | 当前页面是否有导航栏,会计算系统导航栏高度,预览区域下移一段距离 |
src | string | 必填项 | 图片的资源路径 |
mode | ImageModeEnum | ImageModeEnum.ASPECT_FIT | 图片的填充模式,可参照uniapp官方提供的 Image 组件的 mode 值 |
width | number | 100 | 图片宽度 |
height | number | 100 | 图片高度 |
tools | string | zoomIn,zoomOut,rotate,reset | 由这四种工具随意组合,【,】拼接而成的字符串 |
showPreview | boolean | true | 是否允许点击图片后展示预览 |
showLoading | boolean | false | 是否展示加载中标识 |
showError | boolean | false | 是否展示加载失败提示 |
Slots
name | desc |
---|
loading | 调整加载中提示 |
error | 覆盖加载失败提示 |
Emits
name | desc |
---|
loaded | 加载成功触发 |
error | 加载失败触发 |
click | 点击图片 |
输入框 Input
基本使用
<ml-input v-model:model-value="modelValue" placeholder="提示文字可自定义" />
<ml-input v-model:model-value="modelValue" :size="inputSize" />
<ml-input v-model:model-value="modelValue" type="password" />
<ml-input v-model:model-value="modelValue" disabled :size="inputSize" />
列表 List
基本使用
基础列表使用示例
<ml-list
ref="listRef"
v-model:error="error"
:data="mockData"
:loading="loading"
:loading-text="'自定义的加载中文本...'"
:finished="finished"
:height="400"
style="width: 100%"
@load="handleLoad"
>
<template #item="{ item }">
<ml-cell
:label="item.label"
:description="item.description"
:value="item.value"
allow-edit
/>
</template>
</ml-list>
import type { ListInstance, MessageInstance } from '@meleon/uni-ui'
const mockData = ref(
new Array(20).fill(0).map((_, index) => {
return {
id: `id-${index}`,
label: `标题${index}`,
description: `描述${index}`,
value: `值${index}`
}
})
)
const listRef = ref<ListInstance>()
const messageRef = ref<MessageInstance>()
const finished = ref(false)
const loading = ref(false)
const error = ref(true)
const handleLoad = () => {
if (!messageRef.value) return
if (mockData.value.length >= 60) {
finished.value = true
}
if (finished.value) {
messageRef.value.success({
content: '所有数据加载完成',
duration: 2000
})
} else {
messageRef.value.primary({
content: '触发 load 事件',
duration: 2000
})
mockData.value = [
...mockData.value,
...new Array(20).fill(0).map((_, index) => {
const idx = mockData.value.length + index
return {
id: `id-${idx}`,
label: `标题${idx}`,
description: `描述${idx}`,
value: `值${idx}`
}
})
]
}
}
onMounted(() => {
if (listRef.value) listRef.value.scrollIntoView('id-10')
})
虚拟列表使用示例
区别于基础列表,虚拟列表不支持调用 load 加载新数据,使用时需要准备好完整的初始数据
默认情况下,页面上仅展示15条数据节点,可以通过传入 pageSize 自定义每页展示的数量
<ml-list :data="mockData" :height="400" virtual-list style="width: 100%">
<template #virtual="{ data }">
<ml-cell
v-for="item in data"
:key="item.id"
:label="item.label"
:description="item.description"
:value="item.value"
allow-edit
></ml-cell>
</template>
</ml-list>
const mockVirtualData = ref(
new Array(100).fill(0).map((_, index) => {
return {
id: `id-${index}`,
label: `标题${index}`,
description: `描述${index}`,
value: `值${index}`
}
})
)
APIs
prop | type | default | desc |
---|
data | WithId[] | [] | 列表数据,需要提供 id 字段用以定位等操作 |
height | number | 必填 | 列表容器的高度 |
itemHeight | number | 58 | 列表项的高度,可控制提示文本的高度及滚动阈值 |
loading | boolean | false | 是否处于加载状态 |
loadingText | string | 加载中... | 加载状态底部的提示文本 |
finished | boolean | false | 是否加载完成 |
finishedText | string | 没有更多了 | 加载完成时,底部的提示文本 |
error | boolean | false | 是否加载失败 |
errorText | string | 加载失败,点击重试 | 加载失败时,底部的提示文本【可点击,重新触发 load 事件】 |
| | | |
virtualList | boolean | false | 是否开启虚拟列表 |
pageSize | number | 15 | 虚拟列表中展示的数量 |
Slots
name | desc |
---|
loading | 加载中 |
error | 加载异常 |
finished | 加载完成 |
virtual | 虚拟列表 |
item | 普通列表的列表项 |
Methods
name | type | desc |
---|
scrollToTop | () => void | 滚动到顶部 |
scrollIntoView | (id: string | number | symbol) => void | 滚动到指定节点【仅支持普通列表】 |
Events
name | desc |
---|
update:error | 更新 error 属性 |
load | 列表滚动到底部触发 |
选择器 Select
基本使用
<ml-select v-model:modelValue="modelValue" multiple :max-tag-count="1">
<ml-option value="1" label="选项1" />
<ml-option value="2" label="选项2" />
<ml-option value="3" label="选项3" />
</ml-select>
开关 Switch
基本使用
<ml-switch v-model="isActive"></ml-switch>
<ml-switch v-model="isActive" type="circle"></ml-switch>
<ml-switch v-model="isActive" type="line"></ml-switch>
APIs
prop | type | default | desc |
---|
modelValue | boolean | false | 是否开启 |
type | circle | square |line | square | 开关类型 |
checkedColor | string | var(--info-color-7) | 激活状态颜色 |
uncheckedColor | string | var(--primary-color-6) | 未激活状态颜色 |
disabled | boolean | false | 是否禁用 |
beforeSwitch | (newVal: boolean) => boolean | Promise | () => true | 切换前触发 |
表格 Table
基本使用
<ml-table
:data="tableData"
size="mini"
stripe
border
:height="200"
:loading="false"
:refresher-enabled="true"
:refresher-interval="2000"
style="width: 100%"
@row-click="onRowClick"
@cell-click="onCellClick"
>
<template #cell="{ column, row }">
<block v-if="column.property === 'gender'">
<ml-tag :model-value="row[column.property]" type="primary" size="mini"></ml-tag>
</block>
<block v-else-if="column.property === 'age'">
<ml-count-to
:to="row[column.property]"
animation
:value-style="{ fontSize: '14px', color: 'var(--info-color-8)' }"
></ml-count-to>
</block>
<text v-else>{{ column.property && row[column.property] }}</text>
</template>
<!-- 。。。这操作有点多余,后面改改 -->
<ml-table-column type="index" fixed="left"></ml-table-column>
<ml-table-column prop="name" label="姓名" fixed></ml-table-column>
<ml-table-column prop="age" label="年龄"></ml-table-column>
<ml-table-column prop="gender" label="性别"></ml-table-column>
</ml-table>
消息提示 Message
基本使用
<ml-message ref="messageRef" />
import type { MessageInstance, MessageOptions } from '@meleon/uni-ui'
const messageRef = ref<MessageInstance>()
const showMessage = (type: MessageOptions['type']) => {
if (!messageRef.value || !type) return
messageRef.value[type]({
content: type + idx.value++,
duration: 2000
})
}
头部导航栏 Navigator
基本使用
<ml-navigator
title="ml-navigator"
title-color="#FFFFFF"
has-back
icon-color="#FFFFFF"
background="#7A98B3"
/>
APIs
prop | type | default | desc |
---|
background | string | var(--primary-color-6) | 导航栏背景,支持纯色、渐变或图片 |
title | string | '' | 导航栏标题 |
titleColor | string | #FFFFFF | 标题颜色 |
titleStyle | Object | {} | 标题样式 |
hasBack | boolean | true | 是否有回退图标 |
iconColor | string | #FFFFFF | 图标颜色 |
iconStyle | Object | {} | 图标样式 |
tools | Array | [] | 图标列表 |
NavigatorToolEntity
prop | type | desc |
---|
icon | string | 图标名 |
color | string | 图标颜色 |
type | return | navigator | 点击图标的事件的类型 |
delta | number可选 | type = return 时,delta 表示回退的页面数 |
path | string可选 | type = navigator 时,path 表示跳转的页面地址 |
Slots
name | desc |
---|
icon | 图标插槽 |
default | 主体内容插槽 |
时间轴 TimeLine
基本使用
<ml-timeline :reverse="reverseCheckedList[0] === 'reverse'">
<ml-timeline-item>
<template #label>
<text>2023-09-08</text>
</template>
<view>The first milestone content</view>
</ml-timeline-item>
<ml-timeline-item>
<template #label>
<text>2023-09-09</text>
</template>
<view>
<view>The second milestone</view>
<view>The second milestone</view>
<view>The second milestone</view>
</view>
</ml-timeline-item>
<ml-timeline-item>
<template #label>
<text> 2023-09-25 </text>
</template>
<view>The third milestone </view>
</ml-timeline-item>
</ml-timeline>
时间选择器 TimePicker
基本使用
<ml-time-picker v-model="value" style="width: 100%">
<template #trigger>
<ml-cell
label="时间选择器"
:value="value"
style="width: 100%"
></ml-cell>
</template>
</ml-time-picker>
进度条 Progress
基本使用
<ml-progress :percent="percent" status="success" />
<ml-progress :percent="templateMap[0].percent">
<template #text="{ percent, decimal }">
<text>进度 {{ (percent * 100).toFixed(decimal) }}%</text>
</template>
</ml-progress>
<ml-progress :percent="percent" type="circle" :size="curSize" status="primary" />
标签页 Tabs
基本使用
<ml-tabs active="a">
<ml-tab value="a" title="标签1" closable>内容1</ml-tab>
<ml-tab value="b" title="标签2" disabled>内容2</ml-tab>
<ml-tab value="c" title="标签3" disabled closable>内容3</ml-tab>
<ml-tab value="d" title="标签4">内容4</ml-tab>
<ml-tab value="e" title="标签5">内容5</ml-tab>
</ml-tabs>
标签 Tag
基本使用
<ml-tag model-value="标签2" type="primary" plain />
<ml-tag model-value="标签3" size="medium" />
<view>closeable: 添加 ml-close 图标,点击可触发 close 事件</view>
<ml-tag model-value="标签1" closable @close="hanldeTagClose" />
<view>editable: 点击后标签会切换成 input 输入框,可修改标签内容 </view>
<ml-tag model-value="标签2" checkable @click="hanldeTagClick" />
<view>checkable: 添加点击样式,触发 click 事件</view>
<ml-tag v-model:model-value="tagValue" editable />
树 Tree
基本使用
<ml-tree
class="tree-wrapper"
ref="treeRef"
v-model:expanded-keys="expandedKeys"
v-model:checked-keys="checkedKeys"
v-model:selected-keys="selectedKeys"
v-model:indeterminate-keys="indeterminateKeys"
:data="treeData"
checkable
selectable
multiple
:auto-expand-parent="false"
@check="handleCheck"
@select="handleSelect"
@expand="handleExpand"
></ml-tree>
<view class="btn-list">
<ml-button type="primary" @click="handleExpandAll">
{{ isExpandAll ? 'Close All' : 'Expand All' }}
</ml-button>
<ml-button type="primary" @click="handleCheckAll">
{{ isCheckAll ? 'Unheck All' : 'Check All' }}
</ml-button>
<ml-button type="primary" @click="handleSelectAll">
{{ isSelectAll ? 'Unselect All' : 'Select All' }}
</ml-button>
<ml-button type="primary" @click="handleExpandNode"> Expand Root </ml-button>
<ml-button type="primary" @click="handleCheckNode"> Check Root </ml-button>
<ml-button type="primary" @click="handleSelectNode"> Select Root </ml-button>
</view>
import type {
TreeDataEntity,
TreeCheckPayload,
TreeExpandPayload,
TreeSelectPayload,
TreeInstance
} from '@meleon/uni-ui/index'
const treeRef = ref<TreeInstance>()
const rootKey = ref('0-0')
const expandedKeys = ref<string[]>(['0-0-0'])
const checkedKeys = ref<string[]>([])
const selectedKeys = ref<string[]>([])
const indeterminateKeys = ref<string[]>([])
// 监听 tree 触发的事件
const handleCheck = (val: string[], payload: TreeCheckPayload) => {
console.log('onCheck', val, payload)
}
const handleExpand = (val: string[], payload: TreeExpandPayload) => {
console.log('onExpand', val, payload)
}
const handleSelect = (val: string[], payload: TreeSelectPayload) => {
console.log('onSelect', val, payload)
}
// 手动调用组件暴露的方法
// 展开节点
const isExpandAll = ref(false)
const handleExpandAll = () => {
if (!treeRef.value) return
isExpandAll.value = !isExpandAll.value
treeRef.value.expandAll(isExpandAll.value)
}
const handleExpandNode = () => {
if (!treeRef.value) return
treeRef.value.expandNode(rootKey.value, true)
}
// 选中节点复选框
const isCheckAll = ref(false)
const handleCheckAll = () => {
if (!treeRef.value) return
isCheckAll.value = !isCheckAll.value
treeRef.value.checkAll(isCheckAll.value)
}
const handleCheckNode = () => {
if (!treeRef.value) return
treeRef.value.checkNode(rootKey.value, true)
}
// 选中节点
const isSelectAll = ref(false)
const handleSelectAll = () => {
if (!treeRef.value) return
isSelectAll.value = !isSelectAll.value
treeRef.value.selectAll(isSelectAll.value)
}
const handleSelectNode = () => {
if (!treeRef.value) return
treeRef.value.selectNode(rootKey.value, true)
}
// 节点数据
const treeData: TreeDataEntity[] = [
{
title: 'Trunk 0-0',
key: '0-0',
children: [
{
title: 'Branch 0-0-0',
key: '0-0-0',
disabled: false,
children: [
{
title: 'Leaf',
key: '0-0-0-0'
},
{
title: 'Leaf',
key: '0-0-0-1'
}
]
},
{
title: 'Branch 0-0-1',
key: '0-0-1',
children: [
{
title: 'Leaf',
key: '0-0-1-0'
}
]
}
]
}
]
APIs
prop | type | default | desc |
---|
data | TreeDataEntity[] | 必填 | 树形数据 |
checkable | boolean | false | 是否显示复选框 |
checkedKeys | string[] | undefined | 选中复选框的节点键值列表 |
defaultCheckedKeys | string[] | [] | 默认选中复选框的节点键值列表 |
indeterminateKeys | string[] | [] | 半选状态的节点键值列表 |
expandedKeys | string[] | 必填 | 展开的节点键值列表 |
defaultExpandedKeys | string[] | [] | 默认展开的节点键值列表 |
autoExpandParent | boolean | true | 是否自动展开父级节点 |
selectable | boolean | false | 是否支持点击文本选中 |
selectedKeys | string[] | undefined | 选中的文本节点键值列表 |
defaultSelectedKeys | string[] | [] | 默认选中的文本节点键值列表 |
multiple | boolean | true | 点击文本节点的选择是否支持多选 |
Slots
name | desc | prop |
---|
title | 自定义文本节点内容 | title |
Emits
name | desc | params |
---|
update:expandedKeys | 更新 expandedKeys【v-model】 | expandedKeys: string[] |
expand | 展开时触发 | 1. expandedKeys: string[]2. { expanded: boolean node: TreeNodeEntity nodeData: TreeDataEntity} |
update:selectedKeys | 更新 selectedKeys【v-model】 | selectedKeys: string[] |
select | 点击文本节点时触发 | 1. selectedKeys: string[]2. { selected: boolean node: TreeNodeEntity nodeData: TreeDataEntity} |
update:checkedKeys | 更新 checkedKeys【v-model】 | checkedKeys: string[] |
check | 点击节点复选框时触发 | 1. checkedKeys: string[]2. { checked: boolean checkedKeys: string[] indeterminateKeys: string[] node: TreeNodeEntity nodeData: TreeDataEntity} |
update:indeterminateKeys | 更新 indeterminateKeys【v-model】 | indeterminateKeys: string[] |
Events
name | desc | params |
---|
getExpandedNodes | 获取展开的节点 | () => TreeNodeEntity[] |
expandNode | 展开指定的节点 | (key: string | string[], expand: boolean) => void |
expandAll | 展开所有节点 | (expandAll: boolean = true) => void |
| | |
getSelectedNodes | 获取选中的节点 | () => TreeNodeEntity[] |
selectNode | 选择指定的节点 | (key: string | string[], selected: boolean) => void |
selectAll | 选择所有节点 | (selectAll: boolean = true) => void |
| | |
getCheckedNodes | 获取选中复选框的节点 | () => TreeNodeEntity[] |
getIndeterminateNodes | 获取半选状态的节点 | () => TreeNodeEntity[] |
checkNode | 选中指定节点的复选框 | (key: string | string[], checked: boolean) => void |
checkAll | 选中所有节点的复选框 | (checkAll: boolean = true) => void |
上传组件 Uploader
基本使用
<template>
<ml-uploader
ref="uploadRef"
v-model:file-list="fileList"
action="http://localhost:3000/api/file/upload"
multiple
show-file-list
:disabled="false"
:auto-upload="false"
:on-change="handleOnChange"
@delete="handleDelete"
>
<template #trigger>
<ml-button type="primary">选择文件</ml-button>
</template>
</ml-uploader>
<ml-button
type="primary"
status="success"
@click="handleSubmit"
>
上传
</ml-button>
</template>
<script lang="ts" setup>
import type { FileItem, UploaderInstance } from '@meleon/uni-ui/ml-uploader'
const fileList = ref<FileItem[]>([])
const handleDelete = () => {
console.log('a', fileList.value)
}
const handleOnChange = (files: FileItem[]) => {
console.log('a', files)
}
const uploadRef = ref<UploaderInstance>()
const handleSubmit = () => {
if (!uploadRef.value) return
uploadRef.value.submit()
}
</script>
APIs
props | type | default | desc |
---|
action | string | () => string | '' | 文件上传的地址 |
autoUpload | boolean | false | 是否自动上传 |
fieldName | string | file | 上传时文件对应的字段名 |
headers | Record<string, string> | {} | 上传时携带的请求头 |
data | Record<string, any> | {} | 上传时 FromData 里其他的数据 |
fileList | FileItem | 必填项 | 展示的文件列表 |
multiple | boolean | false | 是否支持同时选择多个文件 |
limit | number | 9 | 最多缓存的文件数量 |
previewSize | number | 100 | 预览区域尺寸 |
disabled | boolean | false | 是否禁用 |
showFileList | boolean | false | 是否展示文件列表 |
sourceType | UploaderSourceTypeEnum | '' | 支持相机或相册,默认都支持 |
beforeUpload | (files: FileItem[]) => boolean | Promise | () => true | 上传前的钩子函数 |
beforeDelete | (file: FileItem) => boolean | Promise | () => true | 删除前的钩子函数 |
Types
FileItem
prop | desc |
---|
path | 图片路径 |
id | 图片id |
deletable | 是否可以被删除 |
UploaderSourceTypeEnum
enum | desc |
---|
ALBUM | album |
CAMERA | camera |
Emits
name | desc |
---|
delete | 文件在缓存中被删除 |
uploaded | 文件上传成功 |
update:fileList | 文件列表更新 |
Methods
name | type | desc |
---|
submit | () => void | 手动上传当前展示的所有文件 |
updateFile | (id: string, file: FileItem) => void | 指定id,更新文件对象 |