初步实现
< template>
< a-button class = " editable-add-btn" style = " margin-bottom : 8px" @click = " handleAdd" > Add</ a-button>
< a-table bordered :data-source = " dataSource" :columns = " columns" >
< template #bodyCell = " { column, text, record }" >
< template v-if = " column.dataIndex === 'name'" >
< div class = " editable-cell" >
< div v-if = " editableData[record.key]" class = " editable-cell-input-wrapper" >
< a-input v-model: value= " editableData[record.key].name" @pressEnter = " save(record.key)" />
< check-outlined class = " editable-cell-icon-check" @click = " save(record.key)" />
</ div>
< div v-else class = " editable-cell-text-wrapper" >
{{ text || ' ' }}
< edit-outlined class = " editable-cell-icon" @click = " edit(record.key)" />
</ div>
</ div>
</ template>
< template v-else-if = " column.dataIndex === 'operation'" >
< a-popconfirm
v-if = " dataSource.length"
title = " Sure to delete?"
@confirm = " onDelete(record.key)"
>
< a> Delete</ a>
</ a-popconfirm>
</ template>
</ template>
</ a-table>
</ template>
< script setup >
import { computed, reactive, ref} from 'vue' ;
import { CheckOutlined, EditOutlined} from "@ant-design/icons-vue" ;
import { cloneDeep} from 'lodash-es' ;
const columns = [
{
title : 'name' ,
dataIndex : 'name' ,
width : '30%' ,
} ,
{
title : 'age' ,
dataIndex : 'age' ,
} ,
{
title : 'address' ,
dataIndex : 'address' ,
} ,
{
title : 'operation' ,
dataIndex : 'operation' ,
} ,
] ;
const dataSource = ref ( [
{
key : '0' ,
name : 'Edward King 0' ,
age : 32 ,
address : 'London, Park Lane no. 0' ,
} ,
{
key : '1' ,
name : 'Edward King 1' ,
age : 32 ,
address : 'London, Park Lane no. 1' ,
} ,
] ) ;
const count = computed ( ( ) => dataSource. value. length + 1 ) ;
const editableData = reactive ( { } ) ;
const edit = key => {
editableData[ key] = cloneDeep ( dataSource. value. filter ( item => key === item. key) [ 0 ] ) ;
} ;
const save = key => {
Object. assign ( dataSource. value. filter ( item => key === item. key) [ 0 ] , editableData[ key] ) ;
delete editableData[ key] ;
} ;
const onDelete = key => {
dataSource. value = dataSource. value. filter ( item => item. key !== key) ;
} ;
const handleAdd = ( ) => {
const newData = {
key : ` ${ count. value} ` ,
name : ` Edward King ${ count. value} ` ,
age : 32 ,
address : ` London, Park Lane no. ${ count. value} ` ,
} ;
dataSource. value. push ( newData) ;
} ;
</ script>
< style lang = " less" scoped >
.editable-cell {
position : relative;
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
padding-right : 24px;
}
.editable-cell-text-wrapper {
padding : 5px 24px 5px 5px;
}
.editable-cell-icon,
.editable-cell-icon-check {
position : absolute;
right : 0;
width : 20px;
cursor : pointer;
}
.editable-cell-icon {
margin-top : 4px;
display : none;
}
.editable-cell-icon-check {
line-height : 28px;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color : #108ee9;
}
.editable-add-btn {
margin-bottom : 8px;
}
}
.editable-cell:hover .editable-cell-icon {
display : inline-block;
}
</ style>
渲染后端接口数据
< script setup >
import { computed, onMounted, reactive, ref} from 'vue' ;
import { CheckOutlined, EditOutlined} from "@ant-design/icons-vue" ;
import { cloneDeep} from 'lodash-es' ;
import axios from "axios" ;
const columns = [
{
name : '姓名' ,
dataIndex : 'name' ,
key : 'name' ,
} ,
{
name : '性别' ,
dataIndex : 'gender' ,
key : 'gender' ,
} ,
{
title : '年龄' ,
dataIndex : 'age' ,
key : 'age' ,
} ,
{
title : '电话' ,
dataIndex : 'phone' ,
key : 'phone' ,
} ,
{
title : '邮箱' ,
key : 'email' ,
dataIndex : 'email' ,
} ,
{
title : '薪资' ,
key : 'salary' ,
dataIndex : 'salary' ,
} ,
{
title : '操作' ,
key : 'action' ,
} ,
] ;
const dataSource = ref ( [ ] ) ;
onMounted ( ( ) => {
axios. get ( "http://127.0.0.1:8889/zdppy_amuserdetail" ) . then ( ( response ) => {
console. log ( "response.data" , response. data) ;
dataSource. value = response. data. data. results;
} )
} )
const count = computed ( ( ) => dataSource. value. length + 1 ) ;
const editableData = reactive ( { } ) ;
const edit = id => {
console. log ( "edit" , editableData, id)
editableData[ id] = cloneDeep ( dataSource. value. filter ( item => id === item. id) [ 0 ] ) ;
} ;
const save = id => {
Object. assign ( dataSource. value. filter ( item => id === item. id) [ 0 ] , editableData[ id] ) ;
delete editableData[ id] ;
} ;
const handleAdd = ( ) => {
const newData = {
key : ` ${ count. value} ` ,
name : ` Edward King ${ count. value} ` ,
age : 32 ,
address : ` London, Park Lane no. ${ count. value} ` ,
} ;
dataSource. value. push ( newData) ;
} ;
</ script>
< template>
< a-button class = " editable-add-btn" style = " margin-bottom : 8px" @click = " handleAdd" > Add</ a-button>
< a-table
bordered
:data-source = " dataSource"
:columns = " columns"
:row-key = " record => record.id"
>
< template #headerCell = " { column }" >
< template v-if = " column.key === 'name'" >
< span>
{{ column.name }}
</ span>
</ template>
< template v-else-if = " column.key === 'gender'" >
< span>
{{ column.name }}
</ span>
</ template>
</ template>
< template #bodyCell = " { column, text, record }" >
< template v-if = " column.dataIndex === 'name'" >
< div class = " editable-cell" >
< div v-if = " editableData[record.id]" class = " editable-cell-input-wrapper" >
< a-input v-model: value= " editableData[record.id].name" @pressEnter = " save(record.id)" />
< check-outlined class = " editable-cell-icon-check" @click = " save(record.id)" />
</ div>
< div v-else class = " editable-cell-text-wrapper" >
{{ text || ' ' }}
< edit-outlined class = " editable-cell-icon" @click = " edit(record.id)" />
</ div>
</ div>
</ template>
< template v-else-if = " column.key === 'action'" >
< a-space wrap >
< a-button size = " small" type = " primary" block > 编辑</ a-button>
< a-button size = " small" block > 详情</ a-button>
< a-button size = " small" danger block > 删除</ a-button>
</ a-space>
</ template>
</ template>
</ a-table>
</ template>
< style lang = " less" scoped >
.editable-cell {
position : relative;
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
padding-right : 24px;
}
.editable-cell-text-wrapper {
padding : 5px 24px 5px 5px;
}
.editable-cell-icon,
.editable-cell-icon-check {
position : absolute;
right : 0;
width : 20px;
cursor : pointer;
}
.editable-cell-icon {
margin-top : 4px;
display : none;
}
.editable-cell-icon-check {
line-height : 28px;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color : #108ee9;
}
.editable-add-btn {
margin-bottom : 8px;
}
}
.editable-cell:hover .editable-cell-icon {
display : inline-block;
}
</ style>
将修改的数据保存到数据库
< script setup >
import { computed, onMounted, reactive, ref} from 'vue' ;
import { CheckOutlined, EditOutlined} from "@ant-design/icons-vue" ;
import { cloneDeep} from 'lodash-es' ;
import axios from "axios" ;
const columns = [
{
name : '姓名' ,
dataIndex : 'name' ,
key : 'name' ,
} ,
{
name : '性别' ,
dataIndex : 'gender' ,
key : 'gender' ,
} ,
{
title : '年龄' ,
dataIndex : 'age' ,
key : 'age' ,
} ,
{
title : '电话' ,
dataIndex : 'phone' ,
key : 'phone' ,
} ,
{
title : '邮箱' ,
key : 'email' ,
dataIndex : 'email' ,
} ,
{
title : '薪资' ,
key : 'salary' ,
dataIndex : 'salary' ,
} ,
{
title : '操作' ,
key : 'action' ,
} ,
] ;
const dataSource = ref ( [ ] ) ;
onMounted ( ( ) => {
axios. get ( "http://127.0.0.1:8889/zdppy_amuserdetail" ) . then ( ( response ) => {
console. log ( "response.data" , response. data) ;
dataSource. value = response. data. data. results;
} )
} )
const count = computed ( ( ) => dataSource. value. length + 1 ) ;
const editableData = reactive ( { } ) ;
const edit = id => {
console. log ( "edit" , editableData, id)
editableData[ id] = cloneDeep ( dataSource. value. filter ( item => id === item. id) [ 0 ] ) ;
} ;
const save = id => {
const data = editableData[ id]
console. log ( "updated data" , data)
axios ( {
method : "put" ,
url : "http://127.0.0.1:8889/zdppy_amuserdetail/" + id,
contentType : "application/json" ,
data,
} ) . then ( resp => {
console. log ( "update" , resp. data) ;
} )
Object. assign ( dataSource. value. filter ( item => id === item. id) [ 0 ] , editableData[ id] ) ;
delete editableData[ id] ;
} ;
const handleAdd = ( ) => {
const newData = {
key : ` ${ count. value} ` ,
name : ` Edward King ${ count. value} ` ,
age : 32 ,
address : ` London, Park Lane no. ${ count. value} ` ,
} ;
dataSource. value. push ( newData) ;
} ;
</ script>
< template>
< a-button class = " editable-add-btn" style = " margin-bottom : 8px" @click = " handleAdd" > Add</ a-button>
< a-table
bordered
:data-source = " dataSource"
:columns = " columns"
:row-key = " record => record.id"
>
< template #headerCell = " { column }" >
< template v-if = " column.key === 'name'" >
< span>
{{ column.name }}
</ span>
</ template>
< template v-else-if = " column.key === 'gender'" >
< span>
{{ column.name }}
</ span>
</ template>
</ template>
< template #bodyCell = " { column, text, record }" >
< template v-if = " column.dataIndex === 'name'" >
< div class = " editable-cell" >
< div v-if = " editableData[record.id]" class = " editable-cell-input-wrapper" >
< a-input v-model: value= " editableData[record.id].name" @pressEnter = " save(record.id)" />
< check-outlined class = " editable-cell-icon-check" @click = " save(record.id)" />
</ div>
< div v-else class = " editable-cell-text-wrapper" >
{{ text || ' ' }}
< edit-outlined class = " editable-cell-icon" @click = " edit(record.id)" />
</ div>
</ div>
</ template>
< template v-else-if = " column.key === 'action'" >
< a-space wrap >
< a-button size = " small" type = " primary" block > 编辑</ a-button>
< a-button size = " small" block > 详情</ a-button>
< a-button size = " small" danger block > 删除</ a-button>
</ a-space>
</ template>
</ template>
</ a-table>
</ template>
< style lang = " less" scoped >
.editable-cell {
position : relative;
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
padding-right : 24px;
}
.editable-cell-text-wrapper {
padding : 5px 24px 5px 5px;
}
.editable-cell-icon,
.editable-cell-icon-check {
position : absolute;
right : 0;
width : 20px;
cursor : pointer;
}
.editable-cell-icon {
margin-top : 4px;
display : none;
}
.editable-cell-icon-check {
line-height : 28px;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color : #108ee9;
}
.editable-add-btn {
margin-bottom : 8px;
}
}
.editable-cell:hover .editable-cell-icon {
display : inline-block;
}
</ style>