当前位置: 首页 > news >正文

vue3 + tsx 表格 Action 单独封装组件用法

前言

先上图看右侧列 action 的 UI 效果:

正常来说,如果一个表格的附带 action 操作,我们一般会放在最右侧的列里面实现,这个时候有些UI 框架支持在 SFC 模板里面定义额外的 solt,当然如果不支持,更通用的做法是通过 vue 的 h 函数来实现,纯粹用 js 或 ts 组装组件方式实现,这种方式很灵活,但有一个弊端,当定义的组件很多的时候,比如上图有4 个Button,还得定义按钮样式和点击事件,代码就显的非常乱。

更为优雅的做法是,把这一小块的功能给单独定义成一个 vue 组件,可以用 SFC 也可以用 JSX/TSX 实现,然后事件通过回调完成,代码就显得非常整洁了。

定义 Action 组件

这里用 tsx 实现:

import { defineComponent, PropType, toRefs } from 'vue'
import { NSpace, NTooltip, NButton, NIcon, NPopconfirm } from 'naive-ui'
import {AreaChartOutlined, DeleteOutlined, EditOutlined,
PlayCircleOutlined,PauseCircleOutlined,RedoOutlined,AlignCenterOutlined} from "@vicons/antd";
import {SolrListActionModel} from "@/service/middleware/types";const props = {row: {type: SolrListActionModel as PropType<SolrListActionModel>}
}export default defineComponent({name: 'SolrTableAction',props,emits: ['start','stop','restart','showLog',],setup(props, ctx) {const handleStartAction = () => {ctx.emit('start')}const handleStopAction = () => {ctx.emit('stop')}const handleRestartAction = () => {ctx.emit('restart')}const handleShowLogAction = () => {ctx.emit('showLog')}return {handleStartAction,handleStopAction,handleRestartAction,handleShowLogAction,...toRefs(props)}},render() {return (<NSpace>{this.row?.start ? <NTooltip trigger={'hover'}>{{default: () => "启动",trigger: () => (<NButtonsize='small'type='info'tag='div'circleonClick={this.handleStartAction}class='btn-edit'><NIcon><PlayCircleOutlined></PlayCircleOutlined></NIcon></NButton>)}}</NTooltip>:""}{this.row?.stop?<NTooltip trigger={'hover'}>{{default: () => "停止",trigger: () => (<NButtonsize='small'type='info'tag='div'circleonClick={this.handleStopAction}class='btn-edit'><NIcon><PauseCircleOutlined></PauseCircleOutlined></NIcon></NButton>)}}</NTooltip>:""}{this.row?.restart?<NTooltip trigger={'hover'}>{{default: () => "重启",trigger: () => (<NButtonsize='small'type='info'tag='div'circleonClick={this.handleRestartAction}class='btn-edit'><NIcon><RedoOutlined></RedoOutlined></NIcon></NButton>)}}</NTooltip>:""}{this.row?.showLog?<NTooltip trigger={'hover'}>{{default: () => "日志",trigger: () => (<NButtonsize='small'type='info'tag='div'circleonClick={this.handleShowLogAction}class='btn-edit'><NIcon><AlignCenterOutlined></AlignCenterOutlined></NIcon></NButton>)}}</NTooltip>:""}{this.$slots.extraAction?.()}</NSpace>)}
})
在 Table 列里面引用

定义好之后,在 table 里面引用就非常简单了,只需要把 props 属性传递一下,然后定义回调处理事件即可:

        const columns = [{title: '服务名',key: 'server_name',align: 'center'},{title: '运行状态',key: 'process_state',align: 'center'},{title: '主机IP',key: 'process_ip',align: 'center'},{title: '启动信息',key: 'process_description',align: 'center'},{title: '操作',key: 'operation',//列宽自适应...COLUMN_WIDTH_CONFIG['operation'](4),align: 'center',render: (row: SolrList)=>{let model=new SolrListActionModel(row)return  h(SolrTableAction, {row: model,onStart: () => {},onStop:()=>{},onRestart:()=>{},onShowLog:()=>{}})}}] as TableColumns<any>
列宽自适应工具类

这个是为了该列的宽度,根据实际情况重新分布:

/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements.  See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with* the License.  You may obtain a copy of the License at**    http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { isNumber, sumBy } from 'lodash'
import type {TableColumns,CommonColumnInfo
} from 'naive-ui/es/data-table/src/interface'export const COLUMN_WIDTH_CONFIG = {selection: {width: 50},index: {width: 50},linkName: {width: 200},linkEllipsis: {style: 'max-width: 180px;line-height: 1.5'},name: {width: 200,ellipsis: {tooltip: true}},state: {width: 120},type: {width: 130},version: {width: 80},time: {width: 180},timeZone: {width: 220},operation: (number: number): CommonColumnInfo => ({fixed: 'right',width: Math.max(30 * number + 12 * (number - 1) + 24, 100)}),userName: {width: 120,ellipsis: {tooltip: true}},ruleType: {width: 120},note: {width: 180,ellipsis: {tooltip: true}},dryRun: {width: 140},times: {width: 120},duration: {width: 120},yesOrNo: {width: 100,ellipsis: {tooltip: true}},size: {width: 100},tag: {width: 160},copy: {width: 50}
}export const calculateTableWidth = (columns: TableColumns) =>sumBy(columns, (column) => (isNumber(column.width) ? column.width : 0))export const DefaultTableWidth = 1800
总结

通用这种单独定义组件的方式,大大提高了我们代码的可读性,并且后续这个组件可以单独扩展和改变样式而不影响主列表页的迭代,最后我们要注意给 h 组件的传递 props 的方式,直接使用 props name:value 的形式即可。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • three完全开源扩展案例02-跳动的音乐
  • Blender新手入门笔记收容所(一)
  • Apache Seata应用侧启动过程剖析——RM TM如何与TC建立连接
  • 【LeetCode:1071. 字符串的最大公因子 + 模拟 + 最大公约数】
  • 【PythonRS】基于Python分块处理大型遥感影像的方法
  • 计算机网络浅谈—什么是 OSI 模型?
  • 普中51单片机:定时器与计数器详解及应用(七)
  • 【eNSP模拟实验】三层交换机实现VLAN通信
  • STL(一)
  • 如何将canvas画布变成一张img图片
  • 光伏电站逆变器选型方法
  • Power BI数据分析可视化实战培训
  • 【UNI-APP】阿里NLS一句话听写typescript模块
  • web后端开发--请求响应
  • QT开发积累——qt中的注释和多行注释的几种方式,函数方法注释生成
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • [LeetCode] Wiggle Sort
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 10个确保微服务与容器安全的最佳实践
  • React 快速上手 - 07 前端路由 react-router
  • Solarized Scheme
  • SpiderData 2019年2月13日 DApp数据排行榜
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 诡异!React stopPropagation失灵
  • 和 || 运算
  • 跨域
  • 区块链分支循环
  • 如何胜任知名企业的商业数据分析师?
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 在Mac OS X上安装 Ruby运行环境
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • 我们雇佣了一只大猴子...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • #pragma 指令
  • #在 README.md 中生成项目目录结构
  • $.each()与$(selector).each()
  • (4.10~4.16)
  • (70min)字节暑假实习二面(已挂)
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (三)SvelteKit教程:layout 文件
  • (四)Android布局类型(线性布局LinearLayout)
  • (一)Linux+Windows下安装ffmpeg
  • (转)大型网站的系统架构
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换