当前位置:   article > 正文

vxe-table编辑单元格动态插槽slot的使用_jeecg中jvxetable表格中名称列的插槽

jeecg中jvxetable表格中名称列的插槽

业务场景:表格中只有特定某一行的的单元格可以编辑,列很多,为每个列写个插槽要写很多重复代码,所以这里使用动态插槽,简化代码量。显示编辑图标,点击编辑图标隐藏。失去焦点保存调后台接口。

方法一、

1、后端返回的数据里可以编辑的行数据添加属性 edit: true;不可编辑的行数据里添加属性 edit: false;

2、把列数组里的插槽和field提取出来为循环使用做准备,如果直接使用导入进来的columns无法显示,所以需要处理后使用。

方法二、可以为每个列名使用相同的插槽名,使代码更简洁。

列名文件示例columns.js

  1. export const columns2 = [{
  2. title: '温差',
  3. field: 'pumpCon',
  4. align: 'center',
  5. width: "160",
  6. editRender: {},
  7. slots: {
  8. edit: 'input_edit',
  9. default: 'input_default',
  10. },
  11. },
  12. {
  13. title: '昨日水',
  14. field: 'yesterdayWater',
  15. align: 'right',
  16. width: "110",
  17. editRender: {},
  18. slots: {
  19. edit: 'input_edit',
  20. default: 'input_default',
  21. },
  22. },
  23. {
  24. title: '累计',
  25. field: 'yesterdayWaterSum',
  26. align: 'right',
  27. width: "110",
  28. },
  29. ]
  1. <!-- input_edit -->
  2. <template #input_edit="{ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, _columnIndex }">
  3. <!-- number -->
  4. <div
  5. v-if="[1].includes(rowIndex) && ['pumpCon'].includes(column.field)"
  6. style="display: flex; align-items: center;justify-content: flex-end;"
  7. >
  8. <vxe-input
  9. v-model="row[column.field]"
  10. type="float"
  11. :min="0"
  12. :max="99999999"
  13. :digits="getDigits(column.title)"
  14. @prev-number="onClickBtn(row, rowIndex, column.field, time)"
  15. @next-number="onClickBtn(row, rowIndex, column.field, time)"
  16. @blur="onBlur(row, rowIndex, column.field, time)"
  17. ></vxe-input>
  18. </div>
  19. <!-- else -->
  20. <div v-else>
  21. {{ row[column.field] }}
  22. </div>
  23. </template>
  24. // Js代码 这里失去焦点就调接口,所以当使用输入框的上下箭头时,加入防抖使用
  25. // 防抖
  26. onClickBtn: debounce((row, rowIndex, field, time)=>{
  27. methods.onBlur(row, rowIndex, field, time);
  28. }, 300),
  29. onBlur(row, rowIndex, field, time) {
  30. let value = row?.[field] || '';
  31. let key = `${rowIndex}-${field}`;
  32. ...
  33. }

方法一、列名文件示例columns.js

  1. export const columns1 = [
  2. {
  3. title: '名称',
  4. field: "heatSourceName",
  5. align: 'left',
  6. width: "160",
  7. slots: { header: 'header_heatSourceName', default: '_heatSourceName' },
  8. },
  9. {
  10. title: "日流量(t/h)",
  11. field: "supTemp",
  12. width: "140",
  13. align: 'right',
  14. sortable: false,
  15. editRender: { autofocus: '.vxe-input--inner' },
  16. slots: { default: '_supTemp', edit: 'edit_supTemp' },
  17. },
  18. {
  19. title: "日热量(GJ/h)",
  20. field: "supPres",
  21. width: "140",
  22. align: 'right',
  23. sortable: false,
  24. editRender: { autofocus: '.vxe-input--inner' },
  25. slots: { default: '_supPres', edit: 'edit_supPres' },
  26. },
  27. {
  28. title: "日压力(Mpa)",
  29. field: "instFlowSup",
  30. width: "160",
  31. align: 'right',
  32. sortable: false,
  33. editRender: { autofocus: '.vxe-input--inner' },
  34. slots: { default: '_instFlowSup', edit: 'edit_instFlowSup' },
  35. }, ...]

循环插槽HTML写法

  1. <vxe-grid ref="xGrid1" v-bind="gridOptions1" :span-method="spanMethods">
  2. <template #header_heatSourceName>
  3. <div class="first-col">
  4. <div class="first-col-top">指标</div>
  5. <div class="first-col-bottom">热源</div>
  6. </div>
  7. </template>
  8. <!-- 分割线,动态插槽写法 -->
  9. <template v-for="item in defaultSlots1" :key="item.field" v-slot:[item.slot]="{ row }">
  10. <div style="display: flex; align-items: center;`justify-content: ${row[item.field] === 'heatSourceName' ? flex-start : flex-end}`"
  11. v-if="row.edit && timeInfo === timeInfo1">
  12. <i class="vxe-cell--edit-icon vxe-icon-edit" style="margin-right: 5px;"></i>{{ row[item.field] }}
  13. </div>
  14. <div v-else>
  15. {{ row[item.field] }}
  16. </div>
  17. </template>
  18. <template v-for="item in editSlots1" :key="item.field" v-slot:[item.slot]="{ row }">
  19. <div v-if="row.edit && timeInfo === timeInfo1">
  20. <vxe-input v-model="row[item.field]" type="number" :min="0" :max="99999999"></vxe-input>
  21. </div>
  22. <div v-else>
  23. {{ row[item.field] }}
  24. </div>
  25. </template>
  26. <!-- 分割线,下面为常规写法 -->
  27. <!-- <template #_supTemp="{ row }">
  28. <div style="display: flex; align-items: center;justify-content: flex-end;"
  29. v-if="row.edit && timeInfo === timeInfo1">
  30. <i class="vxe-cell--edit-icon vxe-icon-edit" style="margin-right: 5px;"></i>{{ row.supTemp }}
  31. </div>
  32. <div v-else>
  33. {{ row.supTemp }}
  34. </div>
  35. </template>
  36. <template #edit_supTemp="{ row }">
  37. <div v-if="row.edit && timeInfo === timeInfo1">
  38. <vxe-input v-model="row.supTemp" type="number" :min="0" :max="99999999"></vxe-input>
  39. </div>
  40. <div v-else>
  41. {{ row.supTemp }}
  42. </div>
  43. </template>
  44. <template #_supPres="{ row }">
  45. <div style="display: flex; align-items: center;justify-content: flex-end;"
  46. v-if="row.edit && timeInfo === timeInfo1">
  47. <i class="vxe-cell--edit-icon vxe-icon-edit" style="margin-right: 5px;"></i>{{ row.supPres }}
  48. </div>
  49. <div v-else>
  50. {{ row.supPres }}
  51. </div>
  52. </template>
  53. <template #edit_supPres="{ row }">
  54. <div v-if="row.edit && timeInfo === timeInfo1">
  55. <vxe-input v-model="row.supPres" type="number" :min="0" :max="99999999"></vxe-input>
  56. </div>
  57. <div v-else>
  58. {{ row.supPres }}
  59. </div>
  60. </template>
  61. <template #_waterCnp="{ row }">
  62. <div style="display: flex; align-items: center;justify-content: flex-end;"
  63. v-if="row.edit && timeInfo === timeInfo1">
  64. <i class="vxe-cell--edit-icon vxe-icon-edit" style="margin-right: 5px;"></i>{{ row.waterCnp }}
  65. </div>
  66. <div v-else>
  67. {{ row.waterCnp }}
  68. </div>
  69. </template>
  70. <template #edit_waterCnp="{ row }">
  71. <div v-if="row.edit && timeInfo === timeInfo1">
  72. <vxe-input v-model="row.waterCnp" type="number" :min="0" :max="99999999"></vxe-input>
  73. </div>
  74. <div v-else>
  75. {{ row.waterCnp }}
  76. </div>
  77. </template> -->
  78. </vxe-grid>

 Js写法

  1. <script>
  2. import {
  3. defineComponent,
  4. ref,
  5. reactive,
  6. toRefs,
  7. computed,
  8. watch,
  9. onMounted,
  10. nextTick,
  11. } from 'vue'
  12. import { columns1 } from './columns.js';
  13. import moment from 'moment'
  14. import { useAppStoreWithOut } from '@/store/modules/app'
  15. export default defineComponent({
  16. setup() {
  17. const appStore = useAppStoreWithOut();
  18. const state = reactive({
  19. timeInfo: moment(appStore.getSysTime).subtract(1, 'day').format('YYYY年MM月DD日'),
  20. timeInfo1: moment(appStore.getSysTime).subtract(1, 'day').format('YYYY年MM月DD日'),
  21. gridOptions1: {
  22. border: true,
  23. height: '100%',
  24. showFooter: false,
  25. showOverflow: true,
  26. 'column-config': { resizable: false },
  27. 'edit-config': {
  28. trigger: 'click', mode: 'cell', showIcon: false },
  29. 'scroll-y': { enable: true, mode: 'wheel' },
  30. columns: computed(() => {
  31. // 拼接序号列
  32. return columns1;
  33. }),
  34. data: computed(() => {
  35. let data = [
  36. {
  37. "heatSourceName": "Leo源",
  38. "supTemp": null,
  39. "supPres": null,
  40. "instFlowSup": null,
  41. "retTemp": null,
  42. "retPres": null,
  43. "muwInstFlow": null,
  44. "heatCnp": null,
  45. "waterCnp": null,
  46. "muwaccFlow": null,
  47. "accHeat": null
  48. },
  49. {
  50. "heatSourceName": "晋源",
  51. "supTemp": "86.89",
  52. "supPres": null,
  53. "instFlowSup": "1028.31",
  54. "retTemp": "41.51",
  55. "retPres": "0.111",
  56. "muwInstFlow": "514.64",
  57. "heatCnp": "7923.92",
  58. "waterCnp": "396.58",
  59. "muwaccFlow": "29207293.83",
  60. "accHeat": "680.0334"
  61. },
  62. {
  63. "heatSourceName": "龙山",
  64. "supTemp": "86.90",
  65. "supPres": null,
  66. "instFlowSup": "514.24",
  67. "retTemp": "41.50",
  68. "retPres": null,
  69. "muwInstFlow": "515.29",
  70. "heatCnp": "3960.97",
  71. "waterCnp": "395.64",
  72. "muwaccFlow": "1148264.05",
  73. "accHeat": "166.2449"
  74. }
  75. ]
  76. data.forEach((item, index) => {
  77. if (index === 1 || index === 2) {
  78. item.edit = true
  79. } else {
  80. item.edit = false
  81. }
  82. });
  83. return data
  84. }),
  85. },
  86. // 合并单元格方法,这里只合并第一行和第二行
  87. spanMethods({ row, $rowIndex, column, data }) {
  88. let fields = ["retTemp"]
  89. let cellValue = row[column.property]
  90. if ($rowIndex == 2 || $rowIndex == 3) {
  91. if (cellValue && fields.includes(column.property)) {
  92. let prevRow = data[$rowIndex - 1]
  93. let nextRow = data[$rowIndex + 1]
  94. if (prevRow && prevRow[column.property] === cellValue) {
  95. return { rowspan: 0, colspan: 0 }
  96. } else {
  97. let countRowspan = 1
  98. while (nextRow && nextRow[column.property] === cellValue) {
  99. nextRow = data[++countRowspan + $rowIndex]
  100. }
  101. if (countRowspan > 1) {
  102. return { rowspan: countRowspan, colspan: 1 }
  103. }
  104. }
  105. }
  106. }
  107. })
  108. // 提取默认插槽
  109. const defaultSlots1 = computed(() => {
  110. return columns1.map((column, index) => {
  111. return {
  112. slot: column.slots.default,
  113. field: column.field,
  114. }
  115. })
  116. })
  117. // 提取编辑插槽
  118. const editSlots1 = computed(() => {
  119. return columns1.map((column, index) => {
  120. return {
  121. slot: column.slots.edit,
  122. field: column.field
  123. }
  124. })
  125. })
  126. }
  127. return {
  128. ...toRefs(state),
  129. defaultSlots1,
  130. editSlots1,
  131. }
  132. },
  133. })
  134. </script>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/692059
推荐阅读
相关标签
  

闽ICP备14008679号