@meleon/uni-ui

A uniapp components library written in vue3 and typescript
2,437 1
Install
npm install @meleon/uni-ui
Latest Version:1.2.0
Vue:3
License:ISC
Last Updated:Sep 24, 2024
Links: GitHub  ·  npm
Maintainer: meleon

开发指南

一、快速上手
演示

使用微信扫描下方的小程序码,在线查看组件的渲染效果。

[注:如果因为网络等原因,小程序码图片无法加载,也可以直接输入 Meleon Uni-ui 关键字查询]

image-20231007221035897

安装
# 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
event dessc
click 点击事件
单元格 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
name desc
default 选择框右侧内容
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](https://github.com/floruitShow2/MeleonUI/blob/HEAD/{
      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,更新文件对象

Related Packages

uview-max

uview-max已兼容vue3,全面的组件和便捷的工具会让您信手拈来,如鱼得水

2,887 0
dr-uview

uview-plus已兼容vue3,全面的组件和便捷的工具会让您信手拈来,如鱼得水

2,697 718
@niuku/uview-plus

uview已兼容vue3,全面的组件和便捷的工具会让您信手拈来,如鱼得水

2,540 4,213
uview-costom

uview-plus已兼容vue3,全面的组件和便捷的工具会让您信手拈来,如鱼得水

2,434 719
cengjifou-uview-ui

uview-plus已兼容vue3,全面的组件和便捷的工具会让您信手拈来,如鱼得水

594 719

Version History

Version Released Vue License
1.2.0 ^3.2.45 ISC
1.1.13 ^3.2.45 ISC
1.1.12 ^3.2.45 ISC
1.1.11 ^3.2.45 ISC
1.1.10 ^3.2.45 ISC