Skip to content

按钮组件

介绍

Buttons是基于naive-ui的按钮组件封装的组件,主要区别是使用配置渲染组件

功能如下:

  • 只需传入一个配置项config,即可生成按次序排列的按钮;
  • 可以设置按钮的显隐、权限、点击事件等;
  • 点击事件增加了配置与事件分离的配置方式。

属性说明:

Buttons有configbtnTypeparamspaceProps四个自定义属性,同时可传入naive-ui的button的所有属性

  • config:按钮配置,必传(BtnItem[]),BtnItem里有以下七个自定义属性,同时可配置naive-ui的button的所有属性:
    • label:按钮文字(string
    • icon:图标(Component
    • vif:是否显示(boolean | ((param?: any) => boolean)
    • disabled:是否禁用(boolean | ((param?: any) => boolean)
    • auth:权限(string[]
    • eventName:点击事件名称(string
    • btnType:按钮类型('tableBtn' | 'other'
  • btnType:按钮类型('tableBtn' | 'other'
  • param:vif函数和点击事件的参数
  • spacePropsn-space组件的属性

基础使用

项目里该组件已全局注册,可直接使用。

vue
<template>
  <Buttons :config="config" :param="row" btnType="tableBtn" @edit="edit" @delete="del"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
  {
    label: '编辑',
    type: 'primary',
    auth: ['BTN00460'],
    eventName: 'edit'
  },
  {
    label: '删除',
    type: 'error',
    auth: ['BTN00459'],
    eventName: 'delete'
  }
]

function edit(row: any) {
  console.log('编辑')
}
function del(row: any) {
  console.log('删除')
}
</script>

图标icon

config.icon,设置按钮图标,直接传入图标组件即可。

vue
<template>
	<Buttons :config="config"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'
import { CashOutline, AddCircle, CloseCircle } from '@vicons/ionicons5'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		icon: CashOutline,
		onClick: () => console.log('详情')
	},
	{
		label: '编辑',
		type: 'primary',
		icon: AddCircle,
		onClick: () => console.log('编辑')
	},
	{
		label: '删除',
		type: 'error',
		icon: CloseCircle,
		onClick: () => console.log('删除')
	}
]
</script>

点击事件

方式一:onClick

通过@click绑定,配置格式为onClick: Function

vue
<template>
	<Buttons :config="config"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		onClick: () => console.log('详情')
	},
	{
		label: '编辑',
		type: 'primary',
		onClick: () => console.log('编辑')
	},
	{
		label: '删除',
		type: 'error',
		onClick: () => console.log('删除')
	}
]
</script>

方式二:eventName

自定义事件:将事件通过v-on传递给组件,在配置里用eventName指定自定义事件的名称。

组件内部将eventName指定的事件绑定到对应按钮的点击事件上。

该方式目的:使配置和事件逻辑分开,方便代码归类整理。

vue
<template>
	<Buttons
		:config="config"
		@details="details"
		@edit="edit"
		@delete="handleDelete"
	></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		eventName: 'details'
	},
	{
		label: '编辑',
		type: 'primary',
		eventName: 'edit'
	},
	{
		label: '删除',
		type: 'error',
		eventName: 'delete'
	}
]

function details() {
	console.log('详情')
}
function edit() {
	console.log('编辑')
}
function handleDelete() {
	console.log('删除')
}
</script>

eventName命名:

该名称为@符后面的名称,格式不做限制,支持camelCasekebab-casePascalCase

例如:自定义事件为@editData="handleEdit",此时eventName可以为以下三种:

  • eventName: 'edit-data'
  • eventName: 'editData'
  • eventName: 'EditData'

事件参数param

点击事件的默认参数是$event

如果给Buttons组件传递了param属性:

  • param就为点击事件的第一参数,$event为第二参数;(注意:两种点击事件都有效)
  • vifdisabledFunction时,该param为参数。
不传param传递param
点击事件onClick: (e: Event) => {}onClick: (param: any, e: Event) => {}
vifvif: () => {}vif: (param: any) => {}
disableddisabled: () => {}disabled: (param: any) => {}

完整例子:

vue
<template>
	<Buttons
		:config="config"
		:param="{ name: '企安' }"
		@edit-data="edit"
	></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		vif: (param: any) => param.name === '企安',
		onClick: (param: any) => {
			console.log(param) // {name: '企安'}
		}
	},
	{
		label: '编辑',
		type: 'primary',
		disabled: (param: any) => param.name === '企安',
		eventName: 'edit-data'
	}
]

function edit(param: any) {
	console.log(param) // {name: '企安'}
}
</script>

param在表格操作列里使用,效果尤为显著。让按钮配置可以不用写在render函数里,vif 和点击事件里也仍然能获取到需要的参数。

按钮显隐vif

config.vif:(boolean | (param?:object)=>boolean),按钮是否显示,不传表示显示。

若组件上传递了paramvif为函数时,param可作为函数的参数。

vue
<template>
	<Buttons :config="config" :param="{ name: '企安' }"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		vif: false,
		onClick: () => console.log('详情')
	},
	{
		label: '编辑',
		type: 'primary',
		vif: (param: any) => param.name === '企安',
		onClick: () => console.log('编辑')
	},
]
</script>

按钮禁用disabled

config.disabled:(boolean | (param?:object)=>boolean),按钮是否禁用,不传表示启用。

若组件上传递了paramdisabled为函数时,param可作为函数的参数。

vue
<template>
	<Buttons :config="config" :param="{ name: '企安' }"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		disabled: true,
		onClick: () => console.log('详情')
	},
	{
		label: '编辑',
		type: 'primary',
		disabled: (param: any) => param.name === '企安',
		onClick: () => console.log('编辑')
	},
]
</script>

按钮权限auth

config.auth:(string[]),设置按钮权限。不传,表示显示按钮。

vue
<template>
	<Buttons
		:config="config"
		@details="details"
		@editData="edit"
		@delete="handleDelete"
	></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		auth: ['BTN00459'],
		eventName: 'details'
	},
	{
		label: '编辑',
		type: 'primary',
		auth: ['BTN00460'],
		eventName: 'EditData'
	},
	{
		label: '删除',
		type: 'error',
		eventName: 'delete'
	}
]

function details() {
	console.log('详情')
}
function edit() {
	console.log('编辑')
}
function handleDelete() {
	console.log('删除')
}
</script>

支持n-button的props

单独配置每个按钮

config配置支持naive-uin-button所有的props,例如:

vue
<template>
	<Buttons :config="config"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		size: 'small'
	},
	{
		label: '编辑',
		type: 'primary',
		circle: true,
		disabled: true
	},
	{
		label: '删除',
		type: 'error',
		dashed: true
	}
]
</script>

统一配置所有按钮

组件上也支持naive-uin-button所有的props。

如果所有按钮的配置是一样的,就可以统一在组件上配置,例如:

vue
<template>
	<Buttons
		:config="config"
		type="primary"
		size="small"
		dashed
	></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情'
	},
	{
		label: '编辑'
	},
	{
		label: '删除',
		type: 'error'
	}
]
</script>

TIP

  • Buttons组件会把除configbtnTypeparamspaceProps@xxx以外的 props,都合并到 config 每一个按钮配置上;
  • 若有同名属性,config里的为主

上述例子,等同于以下配置:

vue
<template>
	<Buttons :config="config"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		size: 'small',
		dashed: true
	},
	{
		label: '编辑',
		type: 'primary',
		size: 'small',
		dashed: true
	},
	{
		label: '删除',
		type: 'error',
		size: 'small',
		dashed: true
	}
]
</script>

按钮类型btnType

针对表格写了一组按钮属性,用于统一表格操作列的按钮,传入btnType="tableBtn"可设置为表格类型

btnType默认是other,即为空

vue
<template>
	<Buttons :config="config" btnType="tableBtn"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		onClick: () => console.log('详情')
	},
	{
		label: '编辑',
		type: 'primary',
		onClick: () => console.log('编辑')
	},
	{
		label: '删除',
		type: 'error',
		onClick: () => console.log('删除')
	}
]
</script>

可给单个按钮设置类型(优先级更高)

vue
<template>
	<Buttons :config="config"></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
	{
		label: '详情',
		type: 'primary',
		btnType: 'tableBtn',
		onClick: () => console.log('详情')
	},
	{
		label: '编辑',
		type: 'primary',
		btnType: 'tableBtn',
		onClick: () => console.log('编辑')
	},
	{
		label: '删除',
		type: 'error',
		onClick: () => console.log('删除')
	}
]
</script>

后续根据项目UI可在组件内添加其他的风格

按钮间距

组件内部使用n-space包裹所有按钮,可通过属性spaceProps设置n-space的属性。

vue
<template>
  <Buttons
    type="primary"
    :config="config"
    :spaceProps="{ vertical: true, size: 30, class: 'bg-red-200' }"
  ></Buttons>
</template>

<script setup lang="tsx">
import type { BtnItem } from 'comp/Buttons'

const config: BtnItem[] = [
  { label: '详情' },
  { label: '编辑' },
  { label: '删除', type: 'error' }
]
</script>

INFO

组件内部:

vue
<template>
	<n-space v-bind="spaceProps">
		<n-button v-for="item in btnList" ...> ... </n-button>
	</n-space>
</template>

naive-ui-table中使用

vue
<template>
  <n-card>
    <NaiveUiTable :columns="columns" :requestApi="getTableList">
      <!-- 表格header按钮 -->
      <template #tableHeader>
        <Buttons :config="headerBtn" @add="add"></Buttons>
      </template>

      <!-- 表格操作列 -->
      <template #operation="row">
        <Buttons
          :config="operationBtn"
          btnType="tableBtn"
          :param="row"
          @details="details"
          @edit="edit"
          @delete="handleDelete"
        ></Buttons>
      </template>
    </NaiveUiTable>
  </n-card>
</template>

<script setup lang="tsx">
import { CashOutline } from '@vicons/ionicons5'
import { NaiveUiTable, type TableColumns } from 'naive-ui-table'
import 'naive-ui-table/dist/style.css'
import type { BtnItem } from 'comp/Buttons'
import { list } from 'api/user'

type Item = Recordable

const headerBtn: BtnItem[] = [
  {
    label: '新增',
    type: 'primary',
    icon: CashOutline,
    auth: ['BTN00458'],
    eventName: 'add'
  }
]

const operationBtn: BtnItem[] = [
  {
    label: '详情',
    type: 'primary',
    icon: CashOutline,
    vif: (row) => row.age > 20,
    auth: ['BTN00459'],
    eventName: 'details'
  },
  {
    label: '编辑',
    type: 'primary',
    disabled: (row) => row.age < 10,
    auth: ['BTN00460'],
    eventName: 'edit'
  },
  {
    label: '删除',
    type: 'error',
    auth: ['BTN00461'],
    eventName: 'delete'
  }
]

const columns: TableColumns<Item> = [
  { title: '姓名', key: 'name' },
  { title: '年龄', key: 'age' },
  { title: '地址', key: 'address' },
  { title: '操作', key: 'operation', fixed: 'right', width: 330 }
]

function add() {
  console.log('新增')
}
function details(data: Item) {
  console.log('详情', data)
}
function edit(data: Item) {
  console.log('编辑', data)
}
function handleDelete(data: Item) {
  console.log('删除', data)
}

async function getTableList(params: object) {
  console.log('params: ', params)
  return await list(params)
}
</script>

Props

属性名称类型是否必须描述
configBtnItem[]按钮配置
btnType'tableBtn' | 'other'按钮类型 (不传默认other,表示为空)
paramanyvif函数和点击事件参数
spacePropsSpacePropsn-space组件的属性
@xxxFunction按钮点击事件,需与 eventName 配合使用
……支持传入 naive-ui 的 button 的所有属性
config配置项类型是否必须描述
labelstring按钮内容
iconComponent图标组件
vifboolean | (param?:any)=>boolean按钮是否回显(不传表示回显)
disabledboolean | (param?:any)=>boolean按钮是否禁用(不传表示启用)
authstring[]按钮权限(不传表示回显)
btnType'tableBtn' | 'other'按钮类型 (不传默认other,表示为空)
eventNamestring按钮点击事件名称,与@xxx保持一致
……支持传入 naive-ui 的 button 的所有属性