Skip to content

Button 按钮 ​

17:06

说明 ​

以 uni-app 原生 button 为基础二次封装,内置六套主题色,支持尺寸、形状、镂空、禁用、加载、节流等状态,可选水波纹点击反馈。内容有三种承载方式:text 属性或默认插槽用于纯文字(组件自动着色),content 插槽用于图标与富样式混排(插槽内文字需自行设置颜色,App 端样式不继承)。

兼容性 ​

平台支持情况
App✅ 支持(水波纹 ripple 不支持,开启时自动退回按压深色反馈)
H5✅ 支持
微信小程序✅ 支持(open-type 开放能力、form-type 表单属性仅小程序生效)

示例 ​

基础用法 ​

默认 default 主题,点击触发 click 事件。

查看源码
vue
<template>
    <view class="btn-wrap">
        <!-- 纯文字用 text 属性传入,组件自动着色(App 端也可正常显示) -->
        <ux-button text="普通按钮" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
/* 按钮默认在块级容器中全宽居中,如需收缩靠左排列用 flex 容器包裹 */
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
</style>

主题类型 type ​

支持 default / primary / success / error / warning / info 六种主题。

查看源码
vue
<template>
    <view class="btn-grid">
        <ux-button v-for="(item, index) in typeList" :key="index" :type="item.type" :text="item.label" custom-class="btn-grid-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
const typeList = [
    { type: 'default', label: 'default' },
    { type: 'primary', label: 'primary' },
    { type: 'success', label: 'success' },
    { type: 'error', label: 'error' },
    { type: 'warning', label: 'warning' },
    { type: 'info', label: 'info' }
];

function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-grid {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
}
.btn-grid-item {
    width: 30%;
    margin-bottom: 12px;
}
</style>

镂空 plain ​

plain=true 时背景透明,仅显示边框和文字。

查看源码
vue
<template>
    <view class="btn-grid">
        <ux-button v-for="(item, index) in typeList" :key="index" :type="item.type" :text="item.label" plain custom-class="btn-grid-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
const typeList = [
    { type: 'default', label: 'default' },
    { type: 'primary', label: 'primary' },
    { type: 'success', label: 'success' },
    { type: 'error', label: 'error' },
    { type: 'warning', label: 'warning' },
    { type: 'info', label: 'info' }
];

function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-grid {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
}
.btn-grid-item {
    width: 30%;
    margin-bottom: 12px;
}
</style>

尺寸大小 size ​

支持 large / default / small 三种尺寸。

查看源码
vue
<template>
    <view class="btn-stack">
        <ux-button v-for="(item, index) in sizeList" :key="index" :size="item.size" type="primary" :text="item.label" custom-class="btn-stack-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
const sizeList = [
    { size: 'large', label: 'large' },
    { size: 'default', label: 'default' },
    { size: 'small', label: 'small' }
];

function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-stack {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}
.btn-stack-item {
    margin-bottom: 12px;
}
</style>

按钮形状 shape ​

shape="square" 小圆角(4px,默认),shape="round" 胶囊,shape="circle" 正圆(需宽高相等,示例只放图标)。

查看源码
vue
<template>
    <view class="btn-wrap">
        <ux-button shape="square" type="primary" text="小圆角" custom-class="btn-item" @click="onClick" />
        <ux-button shape="round" type="primary" text="胶囊" custom-class="btn-item" @click="onClick" />
        <!-- circle 为正圆(需宽高相等),故只放图标;带文字会撑成椭圆 -->
        <ux-button shape="circle" type="primary" icon="star" custom-class="btn-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

自定义圆角 border-radius ​

border-radius 优先级高于 shape 预设,可定制任意圆角值(单位px);传 0 即为真直角。

查看源码
vue
<template>
    <view class="btn-wrap">
        <!-- border-radius(单位px)优先级高于 shape 预设,可定制任意圆角;传 0 即为真直角 -->
        <ux-button shape="square" :border-radius="0" type="primary" text="直角 0" custom-class="btn-item" @click="onClick" />
        <ux-button :border-radius="4" type="primary" text="圆角 4" custom-class="btn-item" @click="onClick" />
        <ux-button :border-radius="12" type="error" plain text="圆角 12" custom-class="btn-item" @click="onClick" />
        <ux-button :border-radius="24" type="success" text="圆角 24" custom-class="btn-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

水波纹 ripple ​

ripple=true 开启点击水波纹效果,ripple-bg-color 自定义波纹颜色。

查看源码
vue
<template>
    <view class="btn-wrap">
        <ux-button ripple type="primary" text="水波纹" custom-class="btn-item" @click="onClick" />
        <ux-button ripple ripple-bg-color="rgba(255, 255, 255, 0.3)" type="error" text="水波纹" custom-class="btn-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

App 端不支持水波纹

App 端 UCSS 无 transform/transition 动画,开启 ripple 时会自动退回按压深色反馈;H5 / 微信小程序可用。

细边框 hair-line ​

hair-line=false 关闭细边框,使用粗边框。

查看源码
vue
<template>
    <view class="btn-wrap">
        <ux-button type="default" text="细边框" custom-class="btn-item" @click="onClick" />
        <ux-button :hair-line="false" type="default" text="粗边框" custom-class="btn-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

加载中 loading ​

loading=true 显示加载状态,按钮不可点击。

查看源码
vue
<template>
    <view class="btn-wrap">
        <ux-button loading type="primary" text="默认文案" loading-text="加载中" custom-class="btn-item" />
        <ux-button loading type="success" text="默认文案" loading-text="加载中" custom-class="btn-item" />
    </view>
    <!-- 加载图标大小 loading-size(单位px,默认按按钮尺寸自动匹配) -->
    <view class="btn-wrap">
        <ux-button loading type="warning" text="默认文案" loading-text="加载中" loading-size="20" custom-class="btn-item" />
    </view>
</template>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

禁用 disabled ​

disabled=true 时按钮置灰不可点击;彩色实心(primary/success/error/warning)隐藏边框,default/info/镂空保留细边框。

查看源码
vue
<template>
    <view class="btn-wrap">
        <ux-button disabled type="primary" text="禁用按钮" custom-class="btn-item" />
        <ux-button disabled plain type="primary" text="禁用镂空" custom-class="btn-item" />
    </view>
    <!-- 彩色实心(primary/success/error/warning)禁用时隐藏边框;default/info/镂空保留细边框 -->
    <view class="btn-wrap">
        <ux-button disabled type="default" text="禁用按钮" custom-class="btn-item" />
        <ux-button disabled type="info" text="禁用按钮" custom-class="btn-item" />
        <ux-button disabled plain type="success" text="禁用镂空" custom-class="btn-item" />
    </view>
</template>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

图标按钮 icon ​

icon 指定图标,icon-size 控制大小,icon-color 控制颜色(默认跟随文字色)。

查看源码
vue
<template>
    <view class="btn-wrap">
        <ux-button type="primary" icon="star" text="图标按钮" custom-class="btn-item" @click="onClick" />
        <ux-button type="error" plain icon="heart" text="图标按钮" custom-class="btn-item" @click="onClick" />
        <ux-button type="default" icon="account" icon-color="#2979ff" text="自定义图标色" custom-class="btn-item" @click="onClick" />
    </view>
    <!-- 仅图标:不传插槽内容则只显示图标,可配合 shape 组成各形态 -->
    <view class="btn-wrap btn-icon-row">
        <ux-button shape="round" icon="star" type="primary" custom-class="btn-item" @click="onClick" />
        <ux-button shape="round" plain icon="heart" type="error" custom-class="btn-item" @click="onClick" />
        <ux-button icon="search" type="success" custom-class="btn-item" @click="onClick" />
        <ux-button plain icon="close" type="default" custom-class="btn-item" @click="onClick" />
    </view>
    <!-- 图标大小 icon-size 与垂直偏移 icon-top(单位px,正数向上) -->
    <view class="btn-wrap btn-icon-row">
        <ux-button type="primary" icon="star" icon-size="20" text="大号图标" custom-class="btn-item" @click="onClick" />
        <ux-button type="primary" icon="star" icon-size="26" :icon-top="2" text="大号图标" custom-class="btn-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
.btn-icon-row {
    margin-top: 8px;
}
</style>

自定义内容 slot ​

纯文字用 text 或默认插槽(自动着色);富自定义内容用 content 插槽,内层文字需自行设 color(App 端样式不继承)。

查看源码
vue
<template>
    <view class="btn-wrap">
        <!-- text 属性:纯文字,组件自动着色 -->
        <ux-button type="primary" text="text 属性" custom-class="btn-item" @click="onClick" />
        <!-- 特色示例:content 插槽富拼装(保留 icon/loading)—— 促销售价"大号加粗价格 + 白底省 ¥100 徽标",
             展示纯文字传达不了的混排能力;页面自定义 class 设色 -->
        <ux-button type="error" custom-class="btn-item" @click="onClick">
            <template #content>
                <text class="slot-price">¥299</text>
                <text class="slot-badge">省 ¥100</text>
            </template>
        </ux-button>
    </view>
</template>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
/* 特色插槽:促销售价——大号加粗白字价格 */
.slot-price {
    color: #ffffff;
    font-size: 20px;
    font-weight: bold;
}
/* 特色插槽:促销徽标——白底半透明胶囊 + 深红字 */
.slot-badge {
    margin-left: 8px;
    padding: 0 8px;
    border-radius: 10px;
    background-color: rgba(255, 255, 255, 0.92);
    color: #ee4d38;
    font-size: 12px;
    line-height: 20px;
}
</style>

占满一行 block ​

block=true 时按钮占满整行宽度。

查看源码
vue
<template>
    <view class="btn-stack">
        <ux-button block type="primary" icon="star" text="占满一行的按钮" custom-class="btn-stack-item" @click="onClick" />
        <ux-button block type="success" plain text="占满一行的按钮" custom-class="btn-stack-item" @click="onClick" />
    </view>
</template>

<script setup lang="uts">
function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-stack {
    display: flex;
    flex-direction: column;
}
.btn-stack-item {
    margin-bottom: 12px;
}
</style>

节流 throttle-time ​

throttle-time 指定点击节流间隔(单位毫秒),该间隔内的连击只触发一次。

查看源码
vue
<template>
    <view class="btn-wrap">
        <!-- throttle-time=毫秒:不到该间隔的连击只生效一次,右侧按钮在快速连点时会明显丢次数 -->
        <ux-button type="primary" text="无节流" custom-class="btn-item" @click="onNormalTap" />
        <ux-button type="error" throttle-time="1000" text="节流 1s" custom-class="btn-item" @click="onTap" />
    </view>
</template>

<script setup lang="uts">
const normalCount = ref(0);
const throttledCount = ref(0);

function onNormalTap(): void {
    normalCount.value++;
    uni.showToast({ title: `未节流:${normalCount.value} 次`, icon: 'none' });
}

function onTap(): void {
    throttledCount.value++;
    uni.showToast({ title: `节流 1s:${throttledCount.value} 次`, icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
.btn-item {
    margin-right: 12px;
    margin-bottom: 12px;
}
</style>

自定义样式 custom-style ​

通过 custom-style 覆盖按钮样式,完全自定义场景下按压反馈(hover/pressing)同样交由样式接管,组件不干预。

查看源码
vue
<template>
    <view class="btn-wrap">
        <!-- 完全自定义场景(黑底白字)组件无法自动推断文字色,用时须在插槽内层显式设 color -->
        <ux-button type="default" :custom-style="customStyle" custom-class="btn-item" @click="onClick">
            <text :style="slotTextStyle">自定义样式</text>
        </ux-button>
    </view>
</template>

<script setup lang="uts">
import { createStyle } from '@/uni_modules/uview-pro-x';

const customStyle = computed((): UTSJSONObject => {
    const style = createStyle();
    style['backgroundColor'] = '#000000';
    style['color'] = '#ffffff';
    return style;
});

const slotTextStyle = computed((): UTSJSONObject => {
    const style = createStyle();
    style['color'] = '#ffffff';
    return style;
});

function onClick(): void {
    uni.showToast({ title: '点击了按钮', icon: 'none' });
}
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}
</style>

API ​

Props ​

属性说明类型默认值版本
customStyle自定义根节点样式string | UTSJSONObject--
customClass自定义根节点样式类string''-
text按钮文本:纯文字用 text 传入或写默认插槽均可,组件自动包带色 text(App 文字颜色已显式处理); 富内容(图标+文字混排、富样式)用 content 插槽,使用者自行控制内层文字颜色string''-
icon图标名称,见 ux-icon 图标集,loading 时自动隐藏string''-
iconSize图标大小,单位px,不传时按按钮尺寸自动匹配string | number''-
iconColor图标颜色,不传时跟随按钮文字色string''-
iconTop图标垂直偏移,单位px,正数向上number0-
block是否占满一行booleanfalse-
hairLine是否细边框booleantrue-
type按钮的预置样式,default,primary,success,error,warning,infoButtonType'default'-
size按钮尺寸,large,default,smallButtonSize'default'-
shape按钮形状:square-小圆角 4px(默认),round-胶囊,circle-正圆;直角请传 border-radius=0ButtonShape'square'-
borderRadius自定义圆角值,单位px,优先级高于 shape 预设;默认 '' 表示未设置(传 0 则显式表达真直角)string | number''-
plain按钮是否镂空booleanfalse-
disabled是否禁止状态booleanfalse-
loading是否加载中booleanfalse-
loadingText加载中显示的文案,不传时沿用按钮文本string''-
loadingSize加载图标的大小,单位px,不传时按按钮尺寸自动匹配string | number''-
scope支付宝小程序,当 open-type 为 getAuthorize 时有效ButtonScope''-
openType开放能力,详见 uni-app button 组件开放能力说明ButtonOpenType''-
formType用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件ButtonFormType''-
appParameter打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效string''-
hoverStopPropagation指定是否阻止本节点的祖先节点出现点击态,微信小程序有效booleanfalse-
lang指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效string'en'-
sessionFrom会话来源,open-type="contact"时有效。只微信小程序有效string''-
sendMessageTitle会话内消息卡片标题,open-type="contact"时有效string''-
sendMessagePath会话内消息卡片点击跳转小程序路径,open-type="contact"时有效string''-
sendMessageImg会话内消息卡片图片,open-type="contact"时有效string''-
showMessageCard是否显示会话内消息卡片,open-type="contact"时有效booleanfalse-
rippleBgColor水波纹的背景颜色string''-
ripple是否开启水波纹效果booleanfalse-
hoverClass按下的类名string''-
dataName额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取string''-
throttleTime节流,一定时间内只能触发一次string | number0-
hoverStartTime按住后多久出现点击态,单位毫秒string | number20-
hoverStayTime手指松开后点击态保留时间,单位毫秒string | number150-

Events ​

事件名说明回调参数版本
click按钮点击event: UniEvent-
getuserinfo获取用户信息回调,detail 中值同 uni.getUserInfoevent: UniEvent-
contact客服消息回调event: UniEvent-
getphonenumberopen-type=getPhoneNumber 时有效event: UniEvent-
error使用开放能力发生错误时回调event: UniEvent-
launchapp打开 APP 成功回调event: UniEvent-
opensetting打开授权设置页并关闭后回调event: UniEvent-
chooseavatar头像选择回调event: UniEvent-
agreeprivacyauthorization用户点击允许授权回调event: UniEvent-

Slots ​

插槽名说明版本
default按钮纯文字内容,组件自动包在带色 text 内并着色(App/H5/小程序到齐),纯文字直接用默认插槽或 text 属性-
content完全自定义按钮文字区(图标/view/富样式混排),原样放置、保留 icon 与 loading,插槽内文字需自行设置 color(App 端样式不继承)-

注意事项 ​

  1. 纯文字优先用 text 属性,组件按 type 自动着色,无需手动处理文字颜色;写默认插槽亦可,组件会自动包一层带色 text。
  2. 富内容用 content 插槽:App 端样式不继承,插槽内的文字须显式设置 color。
  3. 定制根节点样式(间距、宽高等)用 custom-class 而非页面原生 class;ux-button 已注册 externalClasses: ['custom-class'],该机制在小程序隔离策略 2.0 下也能把页面类穿透进组件生效。
  4. border-radius 优先级高于 shape 预设,可定制任意圆角,传 0 即为真直角(直角不是 shape 档位)。
  5. shape="circle" 为正圆,需宽高相等,带文字会撑成椭圆;与 block 同传时自动降级为 round。
  6. disabled / loading 状态下的点击会被组件内部守卫拦截,不触发 click;彩色实心类型(primary/success/error/warning)禁用时隐藏边框。
  7. loading 时 icon 自动隐藏,仅保留加载图标与文案;App 端原生 loading 图标固定黑色,组件改用 ux-loading + 文案实现。
  8. 水波纹 ripple 仅 H5 / 微信小程序支持,App 端开启时退回按压深色反馈。
  9. open-type(开放能力)/ form-type(表单)等属性仅微信小程序生效,App / H5 端忽略。
  10. throttle-time 为点击节流间隔(毫秒),间隔内的连续点击只触发一次。