@macroui/macroui-vue

基于 Vue 3 + MacroUI 兼容 Element Plus API 风格的组件库
179,888
Install
npm install @macroui/macroui-vue@2.19.0
Latest Version:2.19.0
Vue:3
License:MIT
Last Updated:Aug 30, 2026
Links: npm
Maintainer: mobiui

@macroui/macroui-vue

Vue 3 + Element Plus API + MacroUI 视觉风格的组件库

npm version license downloads

🎯 @macroui/macroui-vue 是基于 Vue 3(Composition API + <script setup>)开发的 90+ 组件库,提供与 Element Plus 完全一致 的 API(组件名、props、events、slots),同时视觉层基于 @macroui/macroui(DaisyUI 风格)与 Tailwind CSS,覆盖 30+ 主题。

  • 官方网站:https://github.com/mobiui/macroui
  • API 兼容:100% Element Plus API(迁移零成本)
  • 主题切换:data-theme CSS 变量
  • TypeScript:完整类型定义
  • 多语言:67+ 语言内置

目录


1. 项目简介

@macroui/macroui-vue 是 Element Plus API 风格 + MacroUI 视觉风格 的 Vue 3 组件库。

1.1 与 Element Plus 的关系

比较项 Element Plus macroui-vue
API 兼容 ✅ ✅ 100% 兼容
主题方案 CSS 变量 + SCSS CSS 变量(DaisyUI)
内置主题数 4 30+
主题切换 静态 SCSS 运行时 data-theme
样式覆盖 SCSS 变量 Tailwind class
体积 ~250KB ~150KB
多语言 55+ 67+

迁移成本 = 0:只需替换 element-plus → @macroui/macroui-vue。

1.2 特性

  • 🎨 30+ MacroUI 主题(light / dark / corporate / synthwave / cyberpunk / dracula ...)
  • 📦 90+ 组件 — 表单、数据展示、反馈、容器、导航全覆盖
  • 🧩 Element Plus 兼容 API — el-button、el-table、el-form、el-input 命名一致
  • 🌐 多语言 (i18n) — 67 种语言内置,支持运行时切换
  • 🛠 TypeScript 优先 — 完整类型定义
  • ⚡ 按需引入 — 全量注册 / 具名导入皆可
  • 🎯 Vue 3 Composition API — 完全基于 <script setup> 风格开发
  • 💡 Tailwind + DaisyUI — 可直接使用 btn btn-primary 等 DaisyUI 类

1.3 适用项目

  • 后台管理系统
  • 中后台 CRUD 页面
  • 数据可视化大屏
  • 表单密集型应用
  • 需要快速统一视觉风格的多端项目

2. 安装

2.1 通过 npm / pnpm / yarn 安装

# npm
npm install @macroui/macroui-vue @macroui/macroui @macroui/macroui-icons vue

# pnpm (推荐)
pnpm add @macroui/macroui-vue @macroui/macroui @macroui/macroui-icons vue

# yarn
yarn add @macroui/macroui-vue @macroui/macroui @macroui/macroui-icons vue

Vue 3 是 peerDependency,必须显式安装。

2.2 peerDependencies

包名 版本
vue >= 3.2.0(推荐 3.4+)

2.3 dependencies

包名 版本 说明
@macroui/macroui ^4.3.0 MacroUI 主题与样式
@macroui/macroui-icons ^2.1.0 图标库
lodash-unified ^1.0.3 工具函数(按需 tree-shake)

2.4 可选 peerDependencies(按需引入时视使用组件而定)

@macroui/macroui-vue 在构建期将这些运行时依赖标记为 external,不会打包进 bundle,请按需安装:

包名 何时需要
@vueuse/core Tooltip / Dropdown / 弹层类组件用到的基础 hook
@popperjs/core el-tooltip、el-dropdown、el-popover 等 Popper 定位
@floating-ui/dom el-floating 工具与新定位算法
lodash-unified 通用工具函数

一键安装建议:

pnpm add @vueuse/core @popperjs/core @floating-ui/dom lodash-unified

3. 快速开始

3.1 完整注册(推荐)

// main.ts
import { createApp } from 'vue'
import App from './App.vue'

// 1. 加载 CSS(**顺序很重要**:先主题,再组件)
import '@macroui/macroui/dist/themes.css'      // MacroUI 主题变量
import '@macroui/macroui/dist/styled.css'      // MacroUI styled 组件类
import '@macroui/macroui-vue/dist/style.css'   // Vue 组件覆盖样式

// 2. 导入组件与插件
import MacrouiVue from '@macroui/macroui-vue'
import { zhCn } from '@macroui/macroui-vue/locale'

// 3. 创建应用
const app = createApp(App)

// 4. 全局注册全部组件 + ElConfigProvider
app.use(MacrouiVue, { locale: zhCn })

// 5. 挂载
app.mount('#app')

3.2 按需引入

// main.ts
import { createApp } from 'vue'
import {
  ElButton,
  ElInput,
  ElTable,
  ElTableColumn,
  ElConfigProvider,
} from '@macroui/macroui-vue'
import { zhCn } from '@macroui/macroui-vue/locale'

import App from './App.vue'

import '@macroui/macroui/dist/themes.css'
import '@macroui/macroui/dist/styled.css'
import '@macroui/macroui-vue/dist/style.css'

const app = createApp(App)

app.use(ElButton)
app.use(ElInput)
app.use(ElTable)
app.use(ElTableColumn)
app.use(ElConfigProvider, { locale: zhCn })

app.mount('#app')

3.3 在组件内使用

<template>
  <div>
    <el-button type="primary" @click="handleClick">主要按钮</el-button>
    <el-input v-model="value" placeholder="请输入" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const value = ref('')
const handleClick = () => {
  ElMessage.success('点击成功!')
}
</script>

3.4 CSS 加载顺序说明

必须按以下顺序加载:
1. themes.css  - 主题变量 (CSS Custom Properties)
2. styled.css  - MacroUI 通用组件类
3. style.css   - Vue 组件的微调和覆盖

颠倒顺序可能导致主题变量被覆盖而出现视觉异常。

3.5 函数式调用(无需注册)

import { ElMessage, ElMessageBox, ElNotification, ElLoading } from '@macroui/macroui-vue'

ElMessage.success('成功')
ElNotification.error('失败')
const loader = ElLoading.service({ text: '加载中...' })

4. 主题系统

4.1 切换主题

通过设置 <html data-theme="..."> 即可切换:

<html data-theme="light">     <!-- 默认 -->
<html data-theme="dark">      <!-- 暗色 -->
<html data-theme="cupcake">   <!-- 糖果粉 -->
<html data-theme="corporate"> <!-- 商务 -->
<html data-theme="dracula">   <!-- 德古拉 -->

4.2 动态切换(带持久化)

// src/utils/theme.ts
import { ref, watchEffect } from 'vue'

const theme = ref(localStorage.getItem('theme') || 'light')

export function useTheme() {
  watchEffect(() => {
    document.documentElement.setAttribute('data-theme', theme.value)
    localStorage.setItem('theme', theme.value)
  })

  const setTheme = (name: string) => {
    theme.value = name
  }

  const toggleDark = () => {
    setTheme(theme.value === 'dark' ? 'light' : 'dark')
  }

  return { theme, setTheme, toggleDark }
}
<!-- 组件中 -->
<script setup lang="ts">
import { useTheme } from '@/utils/theme'
const { theme, setTheme } = useTheme()
</script>

<template>
  <el-select v-model="theme" @change="setTheme">
    <el-option label="浅色" value="light" />
    <el-option label="暗色" value="dark" />
    <el-option label="赛博朋克" value="cyberpunk" />
  </el-select>
</template>

4.3 内置主题清单(30+)

light、dark、cupcake、bumblebee、emerald、corporate、synthwave、retro、cyberpunk、valentine、halloween、garden、forest、aqua、lofi、pastel、fantasy、wireframe、black、luxury、dracula、cmyk、autumn、business、acid、lemonade、night、coffee、winter、dim、nord、abyss、silk、caramellatte、sunset。

4.4 自定义主题

/* src/styles/theme.css */
[data-theme="mytheme"] {
  /* HSL 格式:H S% L% */
  --p: 220 90% 56%;     /* primary */
  --pc: 0 0% 100%;
  --s: 160 84% 39%;
  --a: 30 90% 50%;
  --n: 220 14% 28%;
  --b1: 0 0% 100%;
  --b2: 220 13% 95%;
  --b3: 220 13% 90%;
  --bc: 220 14% 10%;
  --in: 198 93% 60%;
  --su: 158 64% 52%;
  --wa: 38 92% 50%;
  --er: 0 91% 71%;
}
<html data-theme="mytheme">

5. 国际化 i18n

5.1 全局配置

import { ElConfigProvider } from '@macroui/macroui-vue'
import zhCn from '@macroui/macroui-vue/locale/lang/zh-cn'
import en from '@macroui/macroui-vue/locale/lang/en'

app.use(ElConfigProvider, {
  locale: zhCn,
  // size: 'default',  // 全局组件尺寸
})

5.2 运行时切换

<template>
  <el-config-provider :locale="locale">
    <app />
  </el-config-provider>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import zhCn from '@macroui/macroui-vue/locale/lang/zh-cn'
import en from '@macroui/macroui-vue/locale/lang/en'

const locale = ref(zhCn)
function switchLang(lang: 'zh' | 'en') {
  locale.value = lang === 'zh' ? zhCn : en
}
</script>

5.3 useLocale Hook

<script setup lang="ts">
import { useLocale } from '@macroui/macroui-vue'
const { t } = useLocale()

console.log(t('el.pagination.total', { total: 100 }))  // '共 100 条'
console.log(t('el.table.empty'))                        // '暂无数据'
</script>

5.4 支持的语言(67 种)

区域 语言
中国大陆 zh-cn
中国香港 zh-hk
中国澳门 zh-mo
中国台湾 zh-tw
亚洲 ja, ko, vi, th, my, hi, bn, ta, te, km, ur, pa, id, ms
欧洲 en, de, fr, es, it, pt, pt-br, nl, ru, pl, tr, el, cs, da, sv, nb-no, fi, hu, ro, bg, uk, sk, hr, sl, sr, ca, eo, eu, et, lv, lt
中东 ar, fa, he
非洲 af, sw, mg
中亚 kk, ky, tk, uz-uz
其他 az, hy-am, ku, ckb, mn

完整语言文件路径:@macroui/macroui-vue/locale/lang/<code>

5.5 扩展新语言

// src/locales/ja.ts
export default {
  name: 'ja',
  el: {
    button: {
      confirm: '確認',
      cancel: 'キャンセル',
    },
    pagination: {
      total: '合計 {total} 件',
    },
  },
}
// 注入到全局
import ja from '@/locales/ja'
app.use(ElConfigProvider, {
  locale: ja,
})

5.6 ⚠️ 重要规则

邮箱地址不要写入语言包,应写死在页面组件中。

✅ 正确:写死在组件中
<template>
  <div>联系我们: support@example.com</div>
</template>

❌ 错误:写入语言包
export default {
  contact: 'support@example.com',
}

6. 全局配置 ElConfigProvider

ElConfigProvider 用于全局配置组件默认值。

<template>
  <el-config-provider
    :locale="locale"
    :size="size"
    :button-type="buttonType"
    :message-options="messageOptions"
    :z-index="zIndex"
  >
    <app />
  </el-config-provider>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import zhCn from '@macroui/macroui-vue/locale/lang/zh-cn'
import type { SizeType, ButtonType } from '@macroui/macroui-vue'

const locale = ref(zhCn)
const size = ref<SizeType>('default')
const buttonType = ref<ButtonType>('primary')
const zIndex = ref(2000)
</script>

6.1 ElConfigProvider Props

Prop 类型 默认 说明
locale Language zhCn 当前语言
size SizeType 'default' 全局尺寸
buttonType ButtonType - 全局按钮类型
messageOptions MessageOptions - Message 全局配置
zIndex number 2000 弹窗 z-index 起始值
namespace string 'el' 组件 CSS 类前缀

6.2 SizeType

'large' | 'default' | 'small' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'

注:扩展尺寸(xs / sm / md / lg / xl)仅 macroui-vue 支持,Element Plus 仅有前三档。


7. 组件完整参考

7.1 基础组件

ElButton — 按钮
<template>
  <el-button>默认按钮</el-button>
  <el-button type="primary">主要按钮</el-button>
  <el-button type="success">成功按钮</el-button>
  <el-button type="warning">警告按钮</el-button>
  <el-button type="danger">危险按钮</el-button>
  <el-button type="info">信息按钮</el-button>
  <el-button plain>朴素按钮</el-button>
  <el-button round>圆角</el-button>
  <el-button circle>圆</el-button>
  <el-button icon="Search">搜索</el-button>
  <el-button loading>加载中</el-button>
  <el-button size="large">大</el-button>
  <el-button>默认</el-button>
  <el-button size="small">小</el-button>
  <el-button size="xs">超小</el-button>

  <el-button-group>
    <el-button icon="ArrowLeft">上一页</el-button>
    <el-button icon="ArrowRight">下一页</el-button>
  </el-button-group>
</template>

Props 关键字段:type('primary' | 'success' | 'warning' | 'danger' | 'info' | 'default')、size、plain、round、circle、loading、disabled、icon、native-type、autofocus、tag、text / bg / link。

Events:click、mousedown。

Slots:default、loading、icon。

ElLink — 文字链接
<el-link href="https://element-plus.org" target="_blank">默认</el-link>
<el-link type="primary">主要</el-link>
<el-link :underline="false">无下划线</el-link>
<el-link disabled>禁用</el-link>
ElText — 文本
<el-text>默认</el-text>
<el-text type="primary">主要</el-text>
<el-text type="danger">危险</el-text>
<el-text size="large">大号</el-text>
<el-text truncated>省略...</el-text>
ElIcon — 图标
<el-icon><Edit /></el-icon>
<el-icon :size="20" color="#ff6b6b"><Search /></el-icon>
ElSpace — 间距
<el-space>
  <el-button>1</el-button>
  <el-button>2</el-button>
</el-space>

<el-space direction="vertical" :size="20">
  <el-card>1</el-card>
  <el-card>2</el-card>
</el-space>

<el-space wrap :size="[10, 20]">
  <el-button v-for="i in 10">按钮{{ i }}</el-button>
</el-space>
ElDivider — 分割线
<el-divider />
<el-divider>文字</el-divider>
<el-divider direction="vertical">垂直</el-divider>
<el-divider border-style="dashed" />
ElScrollbar — 滚动条
<el-scrollbar height="200px">
  <p v-for="i in 50">{{ i }}</p>
</el-scrollbar>

7.2 表单组件

ElInput — 输入框
<template>
  <el-input v-model="value" placeholder="请输入" />
  <el-input v-model="value" size="large" />
  <el-input v-model="value" disabled />
  <el-input v-model="value" clearable />
  <el-input v-model="value" show-password />
  <el-input v-model="value" :prefix-icon="Search" />
  <el-input v-model="value" type="textarea" :rows="4" />
  <el-input v-model="url">
    <template #prepend>https://</template>
    <template #append>.com</template>
  </el-input>
  <el-input v-model="value" maxlength="10" show-word-limit />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Search } from '@macroui/macroui-icons'
const value = ref('')
const textarea = ref('')
const url = ref('')
</script>

Props:modelValue、type、placeholder、disabled、clearable、show-password、prefix-icon、suffix-icon、maxlength、minlength、show-word-limit、autocomplete、name、size、input-style。

Events:update:modelValue、input、change、focus、blur、clear、keydown、keyup。

Slots:prefix、suffix、prepend、append。

ElInputNumber — 数字输入
<el-input-number v-model="num" :min="1" :max="10" :step="1" />
<el-input-number v-model="num" controls-position="right" />
<el-input-number v-model="num" :precision="2" :step="0.1" />
ElInputTag — 标签输入
<el-input-tag v-model="tags" placeholder="输入后回车" />
ElInputOtp — 一次性密码
<el-input-otp v-model="otp" :length="6" />
ElSelect — 选择器
<el-select v-model="value" placeholder="请选择" clearable filterable>
  <el-option label="选项A" value="A" />
  <el-option label="选项B" value="B" />
  <el-option-group label="分组1">
    <el-option label="选项C" value="C" />
  </el-option-group>
</el-select>

<el-select v-model="values" multiple collapse-tags>
  <el-option v-for="o in options" :key="o.value" :label="o.label" :value="o.value" />
</el-select>

Props:modelValue、multiple、disabled、size、clearable、filterable、remote、loading-text、no-match-text、no-data-text、placeholder、collapse-tags、multiple-limit、value-key。

ElOption / ElOptionGroup

ElOption Props:value、label、disabled。

ElOptionGroup Props:label、disabled。

ElCascader — 级联选择
<el-cascader
  v-model="value"
  :options="options"
  :props="{ value: 'id', label: 'name' }"
  clearable
  filterable
/>

Props:modelValue、options、props、size、placeholder、disabled、clearable、filterable、show-all-levels、collapse-tags、separator、before-filter、max-collapse-tags。

ElTreeSelect — 树形选择
<el-tree-select v-model="value" :data="treeData" :props="defaultProps" />
ElTree — 树形控件
<el-tree
  :data="data"
  :props="{ children: 'children', label: 'name' }"
  show-checkbox
  node-key="id"
  default-expand-all
  @check-change="handleCheck"
/>

<el-tree :load="loadNode" lazy :props="defaultProps" />
ElTreeV2 — 虚拟树
<el-tree-v2 :data="data" :props="{ label: 'name' }" />
ElCheckbox — 多选框
<el-checkbox v-model="checked">选项</el-checkbox>

<el-checkbox-group v-model="list">
  <el-checkbox value="A">A</el-checkbox>
  <el-checkbox value="B">B</el-checkbox>
</el-checkbox-group>

<el-checkbox :true-value="1" :false-value="0" v-model="value" />
ElCheckboxGroup / ElCheckboxButton
<el-checkbox-group v-model="list">
  <el-checkbox-button value="A">A</el-checkbox-button>
  <el-checkbox-button value="B">B</el-checkbox-button>
</el-checkbox-group>
ElRadio — 单选
<el-radio v-model="radio" :label="1">男</el-radio>
<el-radio-group v-model="radio">
  <el-radio :label="1">男</el-radio>
  <el-radio :label="2">女</el-radio>
</el-radio-group>

<el-radio-group v-model="radio">
  <el-radio-button :label="1">男</el-radio-button>
  <el-radio-button :label="2">女</el-radio-button>
</el-radio-group>
ElSwitch — 开关
<el-switch v-model="value" />
<el-switch v-model="value" active-text="开" inactive-text="关" />
<el-switch v-model="value" inline-prompt active-text="Y" inactive-text="N" />
<el-switch v-model="value" loading />
ElSlider — 滑块
<el-slider v-model="value" :min="0" :max="100" />
<el-slider v-model="range" range :min="0" :max="100" :step="10" />
<el-slider v-model="marks" :marks="{ 0: '0°C', 50: '50°C', 100: '100°C' }" />
ElRate — 评分
<el-rate v-model="rate" />
<el-rate v-model="rate" show-score :max="10" />
<el-rate v-model="rate" allow-half />
ElColorPicker — 颜色选择器
<el-color-picker v-model="color" show-alpha />
<el-color-picker v-model="color" color-format="hex" />
<el-color-picker v-model="color" :predefine="['#ff4500', '#ff8c00']" />
ElDatePicker — 日期选择器
<el-date-picker v-model="date" type="date" placeholder="选择日期" />
<el-date-picker v-model="range" type="daterange" />
<el-date-picker v-model="month" type="month" />
<el-date-picker v-model="year" type="year" />
<el-date-picker v-model="datetime" type="datetime" />
ElTimePicker — 时间选择器
<el-time-picker v-model="time" placeholder="选择时间" />
<el-time-picker v-model="range" is-range />
<el-time-picker v-model="time" format="HH:mm" arrow-control />
ElTimeSelect — 时间段选择
<el-time-select
  v-model="time"
  start="08:30"
  end="18:30"
  step="00:15"
  placeholder="选择时间"
/>
ElUpload — 上传
<el-upload
  action="/api/upload"
  :headers="{ token: 'xxx' }"
  :before-upload="beforeUpload"
  :on-success="onSuccess"
  :on-error="onError"
>
  <el-button>点击上传</el-button>
</el-upload>

<el-upload drag>
  <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  <div class="el-upload__text">
    将文件拖到此处,或<em>点击上传</em>
  </div>
</el-upload>
ElForm — 表单
<template>
  <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username" />
    </el-form-item>
    <el-form-item label="邮箱" prop="email">
      <el-input v-model="form.email" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submit">提交</el-button>
      <el-button @click="reset">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { FormInstance, FormRules } from '@macroui/macroui-vue'

const formRef = ref<FormInstance>()
const form = ref({ username: '', email: '' })

const rules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 20, message: '长度在 3-20', trigger: 'blur' },
  ],
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { type: 'email', message: '邮箱格式不正确', trigger: 'blur' },
  ],
}

const submit = async () => {
  if (!await formRef.value?.validate()) return
}

const reset = () => formRef.value?.resetFields()
</script>

Form Methods(ref):validate(cb?)、validateField(props, cb?)、resetFields()、clearValidate(props?)、scrollToField(prop)。

ElFormItem Props:prop、label、label-width、required、rules、error、show-message、inline-message、size。

ElMention — @提及
<el-mention
  v-model="value"
  :options="[{ value: '张三', label: '张三' }]"
  :prefix="['@', '#']"
/>
ElAutocomplete — 自动补全
<el-autocomplete
  v-model="value"
  :fetch-suggestions="querySearch"
  @select="handleSelect"
/>

7.3 数据展示

ElTable — 表格
<el-table
  :data="tableData"
  stripe
  border
  height="400"
  @selection-change="handleSelection"
>
  <el-table-column type="selection" width="55" />
  <el-table-column type="index" label="#" width="60" />
  <el-table-column prop="name" label="姓名" sortable />
  <el-table-column prop="age" label="年龄" sortable />
  <el-table-column prop="address" label="地址" show-overflow-tooltip />
  <el-table-column label="操作" width="120" fixed="right">
    <template #default="{ row }">
      <el-button size="small" @click="edit(row)">编辑</el-button>
    </template>
  </el-table-column>
</el-table>

<el-pagination
  v-model:current-page="page"
  v-model:page-size="size"
  :total="total"
  layout="total, sizes, prev, pager, next, jumper"
/>

关键 Props:data、height、max-height、stripe、border、size、fit、show-header、highlight-current-row、row-class-name、row-style、cell-class-name、cell-style、empty-text、show-summary、summary-method、span-method、lazy、load、tree-props、default-expand-all、default-sort。

关键 Events:select、select-all、selection-change、cell-click、row-click、row-dblclick、sort-change、current-change、expand-change、filter-change。

ElTableColumn — 表格列

关键 Props:type(selection / index / expand)、prop、label、width、min-width、fixed、sortable、sort-orders、sort-method、sort-by、resizable、formatter、show-overflow-tooltip、align、header-align、class-name、label-class-name、selectable、reserve-selection、filters、filter-placement、filter-multiple、filter-method、filtered-value、render-header。

ElTableV2 — 虚拟表格
<el-table-v2 :columns="columns" :data="data" :width="800" :height="400" fixed />
ElPagination — 分页
<el-pagination
  v-model:current-page="currentPage"
  v-model:page-size="pageSize"
  :total="100"
  :page-sizes="[10, 20, 50, 100]"
  layout="total, sizes, prev, pager, next, jumper"
  background
/>
ElTag — 标签
<el-tag>标签1</el-tag>
<el-tag type="success">成功</el-tag>
<el-tag type="warning" closable>警告</el-tag>
<el-tag type="danger" effect="dark">危险</el-tag>
<el-tag size="large">大号</el-tag>
<el-tag round>圆角</el-tag>
<el-check-tag v-model="checked">可选中</el-check-tag>
ElBadge — 徽章
<el-badge :value="12">
  <el-button>按钮</el-button>
</el-badge>

<el-badge :value="3" :max="9">
  <el-button>≤9</el-button>
</el-badge>

<el-badge is-dot>
  <el-button>红点</el-button>
</el-badge>
ElAvatar — 头像
<el-avatar :size="50" src="user.jpg" />
<el-avatar :size="50" icon="User" />
<el-avatar :size="50">USER</el-avatar>
<el-avatar-group>
  <el-avatar src="1.jpg" />
  <el-avatar src="2.jpg" />
</el-avatar-group>
ElSkeleton — 骨架屏
<el-skeleton v-if="loading" :rows="5" animated />

<el-skeleton>
  <template #template>
    <el-skeleton-item variant="image" style="width: 200px; height: 100px;" />
    <el-skeleton-item variant="h1" />
    <el-skeleton-item variant="text" :rows="3" />
  </template>
  <template #default>真实内容</template>
</el-skeleton>
ElProgress — 进度条
<el-progress :percentage="50" />
<el-progress :percentage="100" status="success" />
<el-progress :percentage="50" type="circle" :width="100" />
<el-progress :percentage="50" :duration="2" striped />
ElEmpty — 空状态
<el-empty description="暂无数据" />
<el-empty :image-size="200">
  <el-button type="primary">重新加载</el-button>
</el-empty>
ElResult — 结果页
<el-result icon="success" title="成功" sub-title="操作已完成">
  <template #extra>
    <el-button type="primary">返回</el-button>
  </template>
</el-result>
ElDescriptions — 描述列表
<el-descriptions title="用户信息" :column="2" border>
  <el-descriptions-item label="用户名">张三</el-descriptions-item>
  <el-descriptions-item label="邮箱">zhang@example.com</el-descriptions-item>
  <el-descriptions-item label="电话">13800138000</el-descriptions-item>
  <el-descriptions-item label="地址" :span="2">北京市朝阳区</el-descriptions-item>
</el-descriptions>
ElStatistic — 统计数值
<el-statistic title="活跃用户" :value="1024" />
<el-statistic :value="12345.67" :precision="2" title="销售额">
  <template #suffix><span>元</span></template>
</el-statistic>
<el-countdown :value="Date.now() + 1000 * 60" title="倒计时" />
ElTimeline — 时间轴
<el-timeline>
  <el-timeline-item timestamp="2024-01-01" placement="top">
    <el-card>创建项目</el-card>
  </el-timeline-item>
  <el-timeline-item timestamp="2024-02-01" type="primary" hollow>
    <el-card>里程碑 1</el-card>
  </el-timeline-item>
</el-timeline>
ElCalendar — 日历
<el-calendar v-model="date">
  <template #date-cell="{ data }">
    <p :class="data.isSelected ? 'is-selected' : ''">
      {{ data.day.split('-').slice(1).join('-') }}
    </p>
  </template>
</el-calendar>
ElImage — 图片
<el-image
  src="image.jpg"
  :fit="'cover'"
  :lazy="true"
  :preview-src-list="[src1, src2]"
/>
ElCarousel — 走马灯
<el-carousel :interval="3000" arrow="always" indicator-position="outside" height="200px">
  <el-carousel-item v-for="item in 4" :key="item">
    <h3>{{ item }}</h3>
  </el-carousel-item>
</el-carousel>
ElCollapse — 折叠面板
<el-collapse v-model="activeNames" accordion>
  <el-collapse-item title="标题1" name="1">内容1</el-collapse-item>
  <el-collapse-item title="标题2" name="2">内容2</el-collapse-item>
</el-collapse>
ElTransfer — 穿梭框
<el-transfer
  v-model="value"
  :data="data"
  filterable
  :props="{ key: 'id', label: 'name' }"
/>
ElWatermark — 水印
<el-watermark content="机密文件">
  <div>有水印内容</div>
</el-watermark>

7.4 反馈组件

ElAlert — 警告提示
<el-alert title="成功提示" type="success" />
<el-alert title="警告提示" type="warning" show-icon />
<el-alert title="错误提示" type="error" description="详细说明" closable />
ElDialog — 对话框
<el-dialog v-model="visible" title="标题" width="500px" :before-close="handleClose">
  <span>内容</span>
  <template #footer>
    <el-button @click="visible = false">取消</el-button>
    <el-button type="primary" @click="confirm">确认</el-button>
  </template>
</el-dialog>

关键 Props:modelValue、title、width、fullscreen、top、modal、append-to-body、lock-scroll、close-on-click-modal、close-on-press-escape、show-close、before-close、draggable、overflow、center、align-center、destroy-on-close、transition。

ElDrawer — 抽屉
<el-drawer v-model="visible" title="抽屉" direction="rtl" size="400px">
  <span>内容</span>
</el-drawer>

关键 Props:modelValue、direction、size、title、modal、drawer-class、wrapper-closable、close-on-press-escape、destroy-on-close、with-header、show-close、z-index、append-to-body、lock-scroll。

ElMessage — 消息提示(函数式)
import { ElMessage } from '@macroui/macroui-vue'

ElMessage.success('操作成功')
ElMessage.warning('警告信息')
ElMessage.error('错误信息')
ElMessage.info('提示信息')

ElMessage({
  message: '带图标',
  type: 'success',
  duration: 3000,
  showClose: true,
  dangerouslyUseHTMLString: true,
  customClass: 'my-message',
  onClose: () => console.log('closed'),
})

MessageOptions:message、type、icon、dangerouslyUseHTMLString、customClass、duration、showClose、center、onClose、offset、appendTo、grouping。

ElMessageBox — 消息弹框
import { ElMessageBox } from '@macroui/macroui-vue'

await ElMessageBox.alert('内容', '标题', { type: 'warning' })

try {
  await ElMessageBox.confirm('确定删除?', '提示', { type: 'warning' })
} catch {
  // 取消
}

const { value } = await ElMessageBox.prompt('请输入名字', '提示', {
  inputPattern: /^.{2,20}$/,
  inputErrorMessage: '长度 2-20',
})
ElNotification — 通知
import { ElNotification } from '@macroui/macroui-vue'

ElNotification({
  title: '标题',
  message: '内容',
  type: 'success',
  position: 'top-right',
  duration: 4500,
})

位置 options:top-right / top-left / bottom-right / bottom-left。

ElPopconfirm — 弹出确认
<el-popconfirm title="确定删除?" @confirm="handleConfirm" @cancel="handleCancel">
  <template #reference>
    <el-button>删除</el-button>
  </template>
</el-popconfirm>
ElTooltip — 文字提示
<el-tooltip content="提示内容" placement="top">
  <el-button>悬停</el-button>
</el-tooltip>

<el-tooltip placement="bottom" effect="light">
  <template #content>
    <p>多行内容</p>
  </template>
  <el-button>亮色</el-button>
</el-tooltip>

关键 Props:content、placement、disabled、offset、transition、show-after、hide-after、controlled、visible、trigger(hover / click / focus / contextmenu)、teleported。

ElPopover — 弹出框
<el-popover placement="top" :width="200" trigger="click">
  <template #default>
    <p>弹出内容</p>
  </template>
  <template #reference>
    <el-button>点击触发</el-button>
  </template>
</el-popover>
ElLoading — 加载状态
<template v-loading="loading">内容</template>

<el-button @click="openFullScreen">全屏 loading</el-button>
<script setup lang="ts">
import { ElLoading } from '@macroui/macroui-vue'
const openFullScreen = () => {
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  setTimeout(() => loading.close(), 3000)
}
</script>

Options:target、fullscreen、lock、text、spinner、background、customClass。

ElTour — 漫游式引导
<el-tour v-model="open">
  <el-tour-step target="#btn1" title="步骤1" description="说明1" />
  <el-tour-step target="#btn2" title="步骤2" description="说明2" />
</el-tour>

7.5 导航组件

ElMenu — 导航菜单
<el-menu :default-active="active" mode="horizontal">
  <el-menu-item index="1">首页</el-menu-item>
  <el-sub-menu index="2">
    <template #title>产品</template>
    <el-menu-item index="2-1">产品A</el-menu-item>
    <el-menu-item index="2-2">产品B</el-menu-item>
  </el-sub-menu>
  <el-menu-item index="3">关于</el-menu-item>
</el-menu>

<el-menu default-active="1" :collapse="collapse">
  ...
</el-menu>

关键 Props:mode(horizontal / vertical)、default-active、collapse、default-openeds、unique-opened、menu-trigger、router、collapse-transition、arrow-icon、ellipsis-icon。

ElMenuItem / ElSubMenu / ElMenuItemGroup
<el-menu-item index="1">
  <template #title>
    <el-icon><Edit /></el-icon>
    <span>编辑</span>
  </template>
</el-menu-item>

<el-sub-menu index="2">
  <template #title>子菜单</template>
  <el-menu-item-group title="分组">
    <el-menu-item index="2-1">选项1</el-menu-item>
  </el-menu-item-group>
</el-sub-menu>
ElTabs — 标签页
<el-tabs v-model="activeName">
  <el-tab-pane label="用户管理" name="first">内容1</el-tab-pane>
  <el-tab-pane label="配置管理" name="second">内容2</el-tab-pane>
  <el-tab-pane label="角色管理" name="third" lazy>内容3</el-tab-pane>
</el-tabs>

<el-tabs type="card">
  ...
</el-tabs>

<el-tabs type="border-card">
  ...
</el-tabs>

关键 Props:v-model、type(card / border-card)、tab-position、closable、addable、editable、before-leave。

ElTabPane — 标签页内容

关键 Props:name、label、disabled、lazy、closable、contextmenu。

ElBreadcrumb — 面包屑
<el-breadcrumb separator="/">
  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  <el-breadcrumb-item :to="{ path: '/list' }">列表</el-breadcrumb-item>
  <el-breadcrumb-item>详情</el-breadcrumb-item>
</el-breadcrumb>
ElDropdown — 下拉菜单
<el-dropdown trigger="click">
  <span class="el-dropdown-link">下拉菜单<el-icon class="el-icon--right"><arrow-down /></el-icon></span>
  <template #dropdown>
    <el-dropdown-menu>
      <el-dropdown-item>选项1</el-dropdown-item>
      <el-dropdown-item disabled>选项2(禁用)</el-dropdown-item>
      <el-dropdown-item divided>选项3</el-dropdown-item>
    </el-dropdown-menu>
  </template>
</el-dropdown>

<el-dropdown split-button @click="handleClick">
  操作
  <template #dropdown>
    <el-dropdown-menu>
      <el-dropdown-item>...</el-dropdown-item>
    </el-dropdown-menu>
  </template>
</el-dropdown>
ElSteps — 步骤条
<el-steps :active="active" finish-status="success" align-center>
  <el-step title="步骤1" description="说明1" />
  <el-step title="步骤2" description="说明2" />
  <el-step title="步骤3" description="说明3" />
</el-steps>

<el-steps :active="1" direction="vertical">
  ...
</el-steps>

关键 Props:space、direction、active、align-center、simple、finish-status、process-status。

ElStep Props:title、description、icon、status。

ElPageHeader — 页头
<el-page-header title="返回" content="详情页" @back="goBack" />
ElAffix — 固钉
<el-affix :offset="100">
  <el-button>固定按钮</el-button>
</el-affix>
ElBacktop — 回到顶部
<el-backtop :right="20" :bottom="20" />
ElAnchor — 锚点
<el-anchor :offset="80">
  <el-anchor-link href="#section-1" title="章节1" />
  <el-anchor-link href="#section-2" title="章节2">
    <el-anchor-link href="#section-2-1" title="章节2-1" />
  </el-anchor-link>
</el-anchor>

7.6 布局组件

ElContainer / ElHeader / ElAside / ElMain / ElFooter
<el-container>
  <el-header>Header</el-header>
  <el-container>
    <el-aside width="200px">Aside</el-aside>
    <el-main>Main</el-main>
  </el-container>
  <el-footer>Footer</el-footer>
</el-container>
ElRow / ElCol — 栅格
<el-row :gutter="20">
  <el-col :span="8">8/24</el-col>
  <el-col :span="8">8/24</el-col>
  <el-col :span="8">8/24</el-col>
</el-row>

<el-row :gutter="20" justify="center">
  ...
</el-row>

<el-row :gutter="20">
  <el-col :xs="24" :sm="12" :md="8" :lg="6">响应式</el-col>
</el-row>

<el-row :gutter="20" type="flex" justify="start" align="middle">
  <el-col :span="6">flex</el-col>
</el-row>

ElRow:gutter、type、justify、align、tag。

ElCol:span、offset、push、pull、xs、sm、md、lg、xl、tag。

ElSplitter — 分隔面板
<el-splitter>
  <el-splitter-panel :size="200">左</el-splitter-panel>
  <el-splitter-panel>右</el-splitter-panel>
</el-splitter>
ElSegmented — 分段控制器
<el-segmented v-model="value" :options="['日', '周', '月']" />
<el-segmented v-model="value" :options="options" size="large" block />
ElBorder — 边框
<el-border>带边框容器</el-border>
<el-border :width="2" color="primary">自定义边框</el-border>
ElInfiniteScroll — 无限滚动指令
<ul v-infinite-scroll="loadMore" :infinite-scroll-delay="200" :infinite-scroll-disabled="disabled">
  <li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>

8. 工具函数与 Hooks

8.1 入口导出

import * as MacrouiVue from '@macroui/macroui-vue'

import {
  ElMessage,
  ElMessageBox,
  ElNotification,
  ElLoading,
} from '@macroui/macroui-vue'

8.2 useLocale

import { useLocale } from '@macroui/macroui-vue'

const { t, locale } = useLocale()
t('el.pagination.total', { total: 100 })

8.3 useZIndex

import { useZIndex } from '@macroui/macroui-vue'

const { initialZIndex, currentZIndex, nextZIndex } = useZIndex()
nextZIndex()  // 取得下一个 z-index

8.4 useNamespace

import { useNamespace } from '@macroui/macroui-vue'

const ns = useNamespace('button')
ns.b()        // 'el-button'
ns.is('disabled')  // 'is-disabled'
ns.m('primary')   // 'el-button--primary'

8.5 类型导出

import type {
  ButtonType,
  ButtonSize,
  SizeType,
  FormInstance,
  FormRules,
  FormItemRule,
  MenuItemRegistered,
  TableInstance,
  TreeInstance,
  UploadFile,
  UploadFiles,
  UploadUserFile,
  TreeNodeData,
  CascaderOption,
  CascaderValue,
  SelectOption,
  SelectOptionGroup,
  MessageOptions,
  MessageType,
  NotificationOptions,
  DateCell,
  CalendarInstance,
} from '@macroui/macroui-vue'

8.6 工具函数

函数 用途
useLocale() 获取当前 locale
useZIndex() z-index 管理
useNamespace(name) 类名前缀
useId() 生成唯一 id
useResizeObserver() 监听 DOM 尺寸
useEventListener() 监听事件
useThrottleFn() 节流
useDebounceFn() 防抖
useDraggable() 拖拽(Dialog 等内部使用)

9. 按需引入

9.1 自动按需(unplugin-vue-components)

npm install -D unplugin-vue-components
// vite.config.ts
import Components from 'unplugin-vue-components/vite'
import { MacrouiVueResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    Components({
      resolvers: [MacrouiVueResolver()],
    }),
  ],
}

9.2 手动按需(推荐用于 SSR)

import {
  ElButton,
  ElInput,
  ElConfigProvider,
} from '@macroui/macroui-vue'

9.3 在 Webpack 中按需

// babel.config.js
module.exports = {
  plugins: [
    ['babel-plugin-import', {
      libraryName: '@macroui/macroui-vue',
      libraryDirectory: 'es',
      style: true,
    }, '@macroui/macroui-vue'],
  ],
}

9.4 性能优化要点(v2.17.84+)

@macroui/macroui-vue 的 ESM 产物里,下述运行时依赖全部走 external,不会被打进 bundle:

依赖 角色
vue peer(必需)
@macroui/macroui-icons 图标默认 external;通过 MacrouiIconsResolver 按需引入
@vueuse/core Tooltip / Dropdown 等使用的基础 hook
@popperjs/core 旧版 Popper 定位(el-tooltip 等)
@floating-ui/dom 新版 Floating 定位(el-floating)
lodash-unified 通用工具函数

当前 ESM 体积拆解:

dist/index.mjs  ~849 KB │ gzip: ~183 KB   // 90+ 组件代码本体
dist/index.js   ~613 KB │ gzip: ~151 KB   // CJS 同步产物
dist/style.css  ~291 KB │ gzip:  ~41 KB   // 全局样式
dist/locale/    ~216 KB │ gzip:   ~6 KB   // 67 种语言(仅打包用到的)

按需引入结论:

  1. 全量注册:app.use(MacrouiVue, ...),体积 ≈ 849 KB / 183 KB (gzip)。
  2. 按需 resolver(推荐):配合 MacrouiVueResolver + MacrouiIconsResolver,仅打包实际用到的组件,通常 < 200 KB (gzip)。
  3. 手动按需:参考 §9.2。

10. SSR / Nuxt

10.1 Nuxt 3 配置

// nuxt.config.ts
export default defineNuxtConfig({
  build: {
    transpile: ['@macroui/macroui-vue'],
  },
  vite: {
    optimizeDeps: {
      include: ['@macroui/macroui-vue'],
    },
  },
  css: [
    '@macroui/macroui/dist/themes.css',
    '@macroui/macroui/dist/styled.css',
    '@macroui/macroui-vue/dist/style.css',
  ],
})
// plugins/macroui.ts
import MacrouiVue from '@macroui/macroui-vue'
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(MacrouiVue)
})

10.2 SSR 注意事项

  • 引用的组件必须出现在 template 中,否则会在 server 端跳过
  • 使用 <client-only> 包裹需要 client 行为的组件(如 ElTooltip、ElPopover)
  • 表单的 el-form SSR 推荐只渲染结构,校验放客户端

11. 浏览器支持

浏览器 版本
Chrome / Edge 最近 2 年
Firefox 最近 2 年
Safari 14+
iOS Safari 14+
Android Chrome 90+
IE ❌ 不支持

支持 Vue 3(>= 3.4)。


12. 开发与构建

12.1 仓库克隆

git clone https://github.com/mobiui/macroui.git
cd macroui-vue
pnpm install

12.2 开发命令

# 库开发模式(监听源码,自动 build)
pnpm dev:lib

# 示例页面(examples/)
pnpm dev:demo

# 仅构建库
pnpm build:lib

# 完整构建(含 locale)
pnpm build:all

# 单元测试
pnpm test
pnpm test:watch
pnpm test:coverage

# E2E 测试
pnpm test:e2e
pnpm test:e2e:ui

# 代码风格
pnpm lint

# TypeScript 类型检查
pnpm typecheck

12.3 目录结构

macroui-vue/
├── examples/                # 示例项目(vite demo)
│   ├── pages/
│   ├── App.vue
│   ├── main.ts
│   └── vite.config.ts
├── packages/
│   ├── components/          # 90+ 组件
│   │   ├── ElButton/
│   │   │   ├── button.vue
│   │   │   ├── props.ts
│   │   │   └── index.ts
│   │   └── ...
│   ├── constants/           # 常量
│   │   ├── aria.ts
│   │   ├── date.ts
│   │   ├── form.ts
│   │   ├── key.ts
│   │   └── size.ts
│   ├── hooks/               # Hooks
│   ├── locale/              # i18n 语言包
│   │   ├── index.ts
│   │   └── lang/
│   ├── styles/              # 组件局部样式
│   └── utils/               # 工具函数
├── tests/
│   ├── unit/                # 单元测试 (vitest)
│   └── e2e/                 # E2E 测试 (playwright)
├── styles/
│   └── index.scss           # 全局样式入口
├── docs/                    # 文档
├── dist/                    # 构建产物
└── types/                   # 全局类型

12.4 创建新组件

mkdir -p packages/components/ElNewComponent
touch packages/components/ElNewComponent/new-component.vue
touch packages/components/ElNewComponent/props.ts
touch packages/components/ElNewComponent/index.ts

props.ts:

import { buildProps } from '@macroui/macroui-vue'
import type { ExtractPropTypes, PropType } from 'vue'

export const newComponentProps = buildProps({
  modelValue: {
    type: [String, Number, Boolean],
    default: '',
  },
  size: {
    type: String,
    values: ['large', 'default', 'small'],
    default: 'default',
  },
  disabled: Boolean,
})

export const newComponentEmits = {
  'update:modelValue': (value: any) => true,
}

export type NewComponentProps = ExtractPropTypes<typeof newComponentProps>
export type NewComponentEmits = typeof newComponentEmits

new-component.vue:

<template>
  <div class="el-new-component" :class="classes">
    <slot />
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { newComponentProps, newComponentEmits } from './props'

defineOptions({ name: 'ElNewComponent' })

const props = defineProps(newComponentProps)
const emit = defineEmits(newComponentEmits)

const classes = computed(() => [
  `el-new-component--${props.size}`,
  { 'is-disabled': props.disabled },
])
</script>

index.ts:

import { withInstall } from '@macroui/macroui-vue'
import NewComponent from './new-component.vue'

export const ElNewComponent = withInstall(NewComponent)
export default ElNewComponent

12.5 添加到 packages/components/index.ts

export { ElNewComponent } from './ElNewComponent'

13. NPM 发布

# 1. 确认登录状态
npm whoami

# 2. 修改 package.json 中的 version(遵循 semver)
# major:破坏性变更
# minor:向下兼容的新功能
# patch:bugfix

# 3. 构建
pnpm build:lib

# 4. 发布
npm publish --access public

13.1 2FA Token 设置

如账户启用 2FA,需要 Granular Access Token:

  1. 访问 https://www.npmjs.com/settings/tokens
  2. 点击 Generate New Token → Granular Access Token
  3. 配置:
    • Token Name: macroui-vue-publish
    • Organization: @macroui
    • Permissions: Publish packages ✅
    • 2FA Bypass: ✅ 必须启用
  4. 生成 Token
npm config set //registry.npmjs.org/:_authToken=YOUR_GRANULAR_TOKEN
npm publish --access public

14. 项目结构

详见 12.3 目录结构。


15. 常见问题

Q1: 样式不生效?

  • ✅ 检查 CSS 加载顺序:themes.css → styled.css → style.css
  • ✅ 确认 <html data-theme="..."> 已设置
  • ✅ 检查 Tailwind config 中是否覆盖了类名前缀
  • ✅ 检查 scoped 样式是否影响组件

Q2: 组件不显示?

  • ✅ 检查是否全局注册(app.use(MacrouiVue))
  • ✅ 检查是否局部注册 + 命名拼写
  • ✅ 检查 <template> 根节点是否就只有一个元素

Q3: TypeScript 类型错误?

  • ✅ 运行 pnpm typecheck
  • ✅ 确保 @types/node 已安装
  • ✅ 检查 tsconfig.json 中 moduleResolution 为 bundler 或 node16

Q4: 主题切换无效?

  • ✅ 注意 data-theme 是属性,不是 CSS class
  • ✅ 自定义主题需匹配 HSL 格式(H S% L%)

Q5: Dialog / Tooltip 不显示?

  • ✅ 检查 z-index(默认 2000+),被遮挡时可显式设置 z-index
  • ✅ 检查 teleported 是否为 true

Q6: 国际化切换无效果?

  • ✅ 使用 el-config-provider 包裹根组件
  • ✅ 邮箱地址不应写在语言包

Q7: 表单校验不生效?

  • ✅ el-form-item 必须设置 prop
  • ✅ rules 中使用 { required: true, message, trigger }
  • ✅ 校验触发使用 await formRef.value?.validate() 是 Promise 式

16. 许可证

MIT License

联系方式:peng.deyou@gmail.com


🔗 相关项目

🔗 链接

  • 仓库地址:https://github.com/mobiui/macroui
  • 问题反馈:https://github.com/mobiui/macroui/issues

Related Packages

@guoyg578/k-ui

可复用的 Vue 3 组件库 (K 前缀),基于 reka-ui (headless) + Tailwind v4 设计令牌。

33,303
weiyun-ui

UI library For Vue

7,638
lemon-ui-vue2

可视化大屏UI库

1,678 5
day-ui

基于 Vue3 的组件库,样式借用 element-plus 的,用于学习使用

1,326 2
weiyun-bui

UI library For Vue

633

Version History

Version Released License
2.19.0 MIT
2.18.7 MIT
2.18.6 MIT
2.18.5 MIT
2.18.4 MIT