<!-- -->
<template>
<div>EditTable</div>
</template>
<script setup lang="ts" name='EditTable' >
import { } from 'vue';
</script >
<style lang="scss" scoped>
</style>
import type { Component } from 'vue'
import EditTable from './editTable/EditTable.vue'
interface APP_COMPONENTS {
[key: string]: Component // 字段扩展声明
}
const components = <APP_COMPONENTS>{
EditTable
}
// 用于全局挂载
export default {
install(app: any) {
for (let com in components) {
app.component(com, components[com])
}
}
}
// 默认导出 用于局部使用
export { EditTable }
import { createApp } from 'vue'
import App from './App.vue'
import MyUI from '@/components/index.ts'
const app = createApp(App)
app.use(MyUI)
app.mount('#app')
<template>
<edit-table></edit-table>
</template>
<!--
描述:
作者:xzl
时间:06月23日132206
-->
<template>
<div>
<edit-table></edit-table>
</div>
</template>
<script setup lang="ts" name="Home">
import { EditTable } from '@/components/index.ts'
import {} from 'vue'
</script>
<style lang="scss" scoped></style>
<!-- 可编辑table -->
<template>
<table border="1" class="edit-table">
<thead>
<tr>
<th v-for="item of tHeader" :key="item.key">
{{ item.text }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) of tBody" :key="item.id">
<td
v-for="(value, key) in item"
:key="key"
@click.stop="showEditInput($event, key, index)"
>
{{ value }}
</td>
</tr>
</tbody>
</table>
</template>
<script setup lang="ts" name="EditTable">
import EditInput from './EditInput.vue'
import { ref, toRefs, reactive } from 'vue'
const props = defineProps({
data: {
type: Object,
default: () => ({
tHeader: [],
tBody: []
})
}
})
const emit = defineEmits(['submit'])
const { tHeader, tBody } = toRefs(props.data)
let editInputApp: any = null
const state = reactive({
key: '',
value: '',
index: '-1',
text: ''
})
// 显示可编辑的input
const showEditInput = (event: any, key: any, index: any) => {
// 1:点击的时候,先移除可编辑的input
editInputApp && removeEditInputApp()
if (!checkEditTable(key)) return // 非 可编辑的选项 跳出
const target = event.target
const oFrag = document.createDocumentFragment()
editInputApp = createApp(EditInput, {
value: target.textContent,
setValue
})
if (editInputApp) {
editInputApp.mount(oFrag)
target.appendChild(oFrag)
target.querySelector('.edit-input').select()
}
setDate({ index, key, text: findText(key) })
}
// 设置编辑的文本数据
function setDate({ index, key, text, value = '' }) {
state.index = index
state.key = key
state.text = text
state.value = value
}
// 寻找 可编辑的 text文本
function findText(key: any) {
const { text } = tHeader.value.find((item: any) => item.key === key)
return text
}
// 设置 可编辑input 修改 table的数据 + 移除可编辑组件
function setValue(value: any) {
state.value = value
emit('submit', { ...state }, removeEditInputApp)
}
// 移除 可编辑的input 并且清空 state状态数据
function removeEditInputApp() {
editInputApp && editInputApp.unmount()
setDate({
key: '',
value: '',
index: '-1',
text: ''
})
}
// 点击 找到 可以编辑的 td项
function checkEditTable(key: any) {
const { editable } = tHeader.value.find((item: any) => item.key === key)
return editable
}
// 点击外层 移除掉 可编辑的事件
window.addEventListener('click', removeEditInputApp, false)
</script>
<style lang="scss" scoped>
.edit-table {
width: 100%;
border-collapse: collapse;
tr {
height: 44px;
}
td {
position: relative;
text-align: center;
cursor: pointer;
}
}
</style>
<!-- 可编辑的input -->
<template>
<input
type="text"
class="edit-input"
:value="value"
@input="onInput"
@blur="onBlur"
@click="onClick"
/>
</template>
<script setup lang="ts" name="EditInput">
import { ref } from 'vue'
const props = defineProps({
value: {
type: String,
default: ''
},
setValue: {
type: Function,
default: () => {}
}
})
const inputVal = ref(props.value)
const onInput = (event: any) => {
inputVal.value = event.target.value.trim()
}
const onBlur = (event: any) => {
props.setValue(inputVal.value)
}
const onClick = (event: any) => {
event.stopPropagation()
}
</script>
<style lang="scss" scoped>
.edit-input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 1px solid yellow;
text-align: center;
outline: none;
}
</style>
import type { Component } from 'vue'
import EditTable from './editTable/EditTable.vue'
interface APP_COMPONENTS {
[key: string]: Component // 字段扩展声明
}
const components = <APP_COMPONENTS>{
EditTable
}
// 用于全局挂载
export default {
install(app: any) {
for (let com in components) {
app.component(com, components[com])
}
}
}
// 默认导出 用于局部使用
export { EditTable }
import { createApp } from 'vue'
import App from './App.vue'
import MyUI from '@/components/index.ts'
const app = createApp(App)
app.use(MyUI)
app.mount('#app')
<!--
描述:
作者:xzl
时间:06月23日132206
-->
<template>
<div>
Home
<edit-table :data="tabelData" @submit="submit"></edit-table>
</div>
</template>
<script setup lang="ts" name="Home">
import { EditTable } from '@/components/index.ts'
import { ref } from 'vue'
const tabelData = ref({
tHeader: [
{
key: 'id',
text: '学号',
editable: false
},
{
key: 'name',
text: '名称',
editable: false
},
{
key: 'age',
text: '年龄',
editable: false
},
{
key: 'chinese',
text: '语文',
editable: true
},
{
key: 'math',
text: '数学',
editable: true
},
{
key: 'english',
text: '英语',
editable: true
}
],
tBody: [
{
id: '1',
name: 'xpl',
age: 16,
chinese: 121,
math: 188,
english: 111
},
{
id: '2',
name: 'ppp',
age: 18,
chinese: 222,
math: 223,
english: 224
},
{
id: '3',
name: 'qqq',
age: 23,
chinese: 331,
math: 332,
english: 333
}
]
})
const submit = ({ index, key, value, text }, removeInput) => {
// console.log('submit', index, key, value, text)
if (tabelData.value.tBody[index][key] != value) {
const cfm = window.confirm(`
你确定讲 ${index} 项
${text} 字段的内容修改威 ${value} 吗?
`)
if (cfm) {
tabelData.value.tBody = tabelData.value.tBody.map((item, idx) => {
index === idx && (item[key] = value)
return item
})
} else {
removeInput()
}
}
}
</script>
<style lang="scss" scoped></style>
初
点击
修改
结果