1. 默认样式可自行修改
// 默认样式可自行修改
.table-edit-remarks {
cursor: text;
padding: 0;
&:hover {
box-shadow: 0 0 0 1px var(--el-color-primary-light-5) inset;
}
}
.table-edit-remarks.is-active-remarks {
box-shadow: 0 0 0 1px var(--el-color-primary) inset!important;
}
[contenteditable]:focus, [contenteditable]:focus-visible {
outline: none;
}
2. ts封装类 可直接复制运行
// --------ts封装类 可直接复制运行 ------------ //
import msgLoading from '@/utils/msgLoading'
import { errorFormTips } from '@/utils/tool'
import api from '@/api'
/**
* 选中表格td class名
*/
const activeClassName = 'is-active-remarks'
/**
* 列td默认class名
*/
const defaultClassName = 'table-edit-remarks'
/**
* 给表格某列添加class 该函数对应el-table cellClassName方法 示例::cell-class-name="({ columnIndex }: any) => cellClassName(columnIndex, 10)"
* @param columnIndex 列下标
* @param className 添加class名
* @param index 哪一列
* @returns
*/
function cellClassName(columnIndex: number, index: number, className = defaultClassName) {
if (columnIndex === index) {
return className
}
return ''
}
/**
* 点击外围输入框光标聚焦在内容尾部
*/
function handleClick(dom: any) {
dom?.focus()
document.execCommand('selectAll', false)
document.getSelection()?.collapseToEnd()
}
/**
* 阻止默认的冒泡事件
*/
function handleChildClick(event: MouseEvent) {
event.stopPropagation()
}
/**
* 聚焦添加class样式
*/
function handleChildfocus(dom: any) {
dom.classList.add(activeClassName)
}
/**
* 失焦提交备注 移除class样式
*/
function handleChildblur(event: any, dom: any, i: number, field: string, res: any, url: string) {
const c_loading = ref()
const innerText = (event?.target?.innerText).replace(/^\s+|\s+$/g, '')
dom.classList.remove(activeClassName)
if (res.result?.list[i][field] === event?.target?.innerText || innerText === '') {
dom!.firstChild.innerText = res.result?.list[i][field]
return false
}
c_loading.value = msgLoading()
api.post(url, { id: res.result?.list[i].id, remarks: innerText }).then((response: any) => {
// 延迟可以看到加载效果 自行去除
setTimeout(() => {
c_loading.value?.close()
c_loading.value = ''
if (!errorFormTips(response, null, null, false)) {
dom!.firstChild.innerText = res.result?.list[i][field]
return false
}
res.result!.list[i][field] = innerText
}, 500)
})
}
// 统计监听的列
const data: any = {}
// 刷新表格结果 用以解决【当使用dialog|drawer 更新内容之后 刷新表格会出现老数据】
const result: any = ref()
/**
* 编辑备注方法
* @param url 请求路径
* @param res 表格的数据结果
* @param className 列的class名
* @param field 表格数据对应的字段
* @returns
*/
function editRemarksFunc(url: string, res: any, className = defaultClassName, field = 'remarks') {
const remarksElements: any = document.getElementsByClassName(className)
if (!remarksElements.length) {
return false
}
result.value = res
const eventListeners: any[] = []
for (let i = 0; i < remarksElements.length; i++) {
remarksElements[i]!.firstChild.innerText = res.result?.list[i][field]
if (data[res.result?.list[i].id] && remarksElements[i]!.firstChild.hasAttribute('contenteditable')) {
continue
}
data[res.result?.list[i].id] = res.result?.list[i].id
remarksElements[i]!.firstChild?.setAttribute('contenteditable', 'true')
// 点击外围输入框光标聚焦在内容尾部
eventListeners.push({ element: remarksElements[i], event: 'click', listener: () => handleClick(remarksElements[i]!.firstChild) })
// 阻止默认的冒泡事件
eventListeners.push({ element: remarksElements[i]!.firstChild, event: 'click', listener: (event: MouseEvent) => handleChildClick(event) })
// 聚焦添加class样式
eventListeners.push({ element: remarksElements[i]!.firstChild, event: 'focus', listener: () => handleChildfocus(remarksElements[i]) })
// 失焦提交备注 移除class样式
eventListeners.push({ element: remarksElements[i]!.firstChild, event: 'blur', listener: (event: MouseEvent) => handleChildblur(event, remarksElements[i], i, field, result.value, url) })
}
// 在重新加载表格时添加事件监听器
function addEventListeners() {
eventListeners.forEach((listener) => {
listener.element.addEventListener(listener.event, listener.listener)
})
}
// 在重新加载表格时移除事件监听器
function removeEventListeners() {
eventListeners.forEach((listener) => {
listener.element.removeEventListener(listener.event, listener.listener)
})
}
// 刷新表格时添加和移除事件监听器
removeEventListeners()
addEventListeners()
}
export {
cellClassName,
editRemarksFunc,
}
3. 运行示例
<script lang="ts" setup>
import { cellClassName, editRemarksFunc } from '@/utils/tableEdit'
// 表格数据加载成功
function loadDataSuccess(res: any) {
nextTick(() => editRemarksFunc('备注更新的api接口', res))
}
</script>
<template>
<el-table :cell-class-name="({ columnIndex }: any) => cellClassName(columnIndex, 10)" />
</template>
4. 运行效果
鼠标悬浮效果
选中效果
鼠标失焦提交更新api
5.继续更新,考虑到需要到msgLoading 组件,今天就一起更新上来
// 本组件命名为 msgLoading.tsx
import { ElMessage } from 'element-plus'
export default function (msg = '数据加载中...') {
return ElMessage({
duration: 0,
customClass: 'custom-msg-loading',
icon: {
render() {
return <el-icon class="is-loading"><svg-icon name="i-ep:loading" /></el-icon>
},
},
message: msg,
})
}
// 全局样式
.custom-msg-loading {
background-color:#fff;
color: var(--el-color-primary);
.is-loading {
color: var(--el-color-primary);
animation: rotating 2s linear infinite;
}
}