欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > vue3 + tsx 表格 Action 单独封装组件用法

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

2024/10/23 19:30:11 来源:https://blog.csdn.net/u010454030/article/details/140327086  浏览:    关键词: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 的形式即可。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com