当前位置:   article > 正文

基于elementPlus二次封装可编辑表格组件_elementplus可编辑表格

elementplus可编辑表格

参考:vue3 二次封装element-plus 表格组件_vue3 + ts+elementui-plus 封装表格分页组件-CSDN博客

组件封装index.vue:

  1. <template>
  2. <el-table
  3. v-loading="listLoading"
  4. :data="tableData"
  5. element-loading-text="Loading"
  6. fit
  7. border
  8. highlight-current-row
  9. :max-height="maxHeight"
  10. :cell-style="tableRowStyle"
  11. @row-click="clickRow"
  12. @selection-change="handleSelectionChange"
  13. :border="true"
  14. ref="table"
  15. @cell-click="showUnitInput"
  16. >
  17. <el-table-column type="selection" width="55" />
  18. <el-table-column
  19. v-for="(item, index) in tableHeader"
  20. :key="index"
  21. :prop="item.prop"
  22. align="center"
  23. :label="item.label"
  24. :min-width="item.minWidth"
  25. >
  26. <template #default="scope">
  27. <!-- 按钮 -->
  28. <div v-if="item.btn">
  29. <el-button
  30. v-for="(k, index) in item.btn"
  31. :key="index"
  32. size="small"
  33. @click="k.func(scope.$index, scope.row)"
  34. >{{ k.name }}</el-button
  35. >
  36. </div>
  37. <!-- 图片 -->
  38. <div v-else-if="item.type == 'img'">
  39. <el-image
  40. style="width: 100px; height: 100px"
  41. :src="scope.row.image"
  42. :fit="fit"
  43. />
  44. </div>
  45. <!-- 数据字典转换 -->
  46. <div v-else-if="item.type == 'dic'">
  47. <!-- <el-link
  48. v-if="item.isline == true"
  49. :type="item.lineType(scope.row[item.prop])"
  50. :underline="false"
  51. >{{ item.formatData(scope.row[item.prop]) }}</el-link
  52. > -->
  53. <div v-for="(ite, index) in listData[item.prop]">
  54. <el-link
  55. v-if="scope.row[item.prop] == ite.key && item.isline == true"
  56. :type="ite.type"
  57. >{{ ite.value }}</el-link
  58. >
  59. <span v-else-if="scope.row[item.prop] == ite.key">{{
  60. ite.value
  61. }}</span>
  62. </div>
  63. </div>
  64. <!-- 编辑 -->
  65. <div v-else-if="item.type == 'edit'">
  66. <input
  67. type="text"
  68. v-model="scope.row[item.prop]"
  69. v-focus
  70. v-if="
  71. tableRowEditId === scope.row.id &&
  72. tableColumnEditIndex === scope.column.id
  73. "
  74. @blur="blurUnitInput(row, column)"
  75. @keyup.enter="blurUnitInput(row, column)"
  76. />
  77. <span v-else>{{ scope.row[item.prop] }}</span>
  78. </div>
  79. <!-- 日期拼接、普通字段 -->
  80. <div v-else>
  81. <span v-if="!item.formatData">
  82. <span v-if="item.isDate == true"
  83. >{{ repString(scope.row[item.prop[0]]) }}-{{
  84. repString(scope.row[item.prop[1]])
  85. }}</span
  86. >
  87. <span v-else>{{ scope.row[item.prop] }}</span>
  88. </span>
  89. <span v-else>
  90. <span>{{ scope.row[k.prop] }}</span>
  91. </span>
  92. </div>
  93. </template>
  94. </el-table-column>
  95. </el-table>
  96. <div class="demo-pagination-block">
  97. <el-pagination
  98. v-model:current-page="currentPage"
  99. v-model:page-size="pageSize"
  100. :page-sizes="[10, 20, 30, 50]"
  101. :small="small"
  102. :disabled="disabled"
  103. :background="background"
  104. layout="total, sizes, prev, pager, next, jumper"
  105. :total="400"
  106. @size-change="handleSizeChange"
  107. @current-change="handleCurrentChange"
  108. style="float: right"
  109. />
  110. </div>
  111. </template>
  112. <script lang="ts">
  113. import { getCurrentInstance, ref } from "vue";
  114. export default {
  115. props: {
  116. tableData: {
  117. type: Array,
  118. default: () => [],
  119. },
  120. tableHeader: {
  121. type: Array,
  122. default: () => [],
  123. },
  124. listLoading: {
  125. type: Boolean,
  126. default: false,
  127. },
  128. maxHeight: {
  129. type: String,
  130. default: "",
  131. },
  132. listData: {
  133. type: Object,
  134. default: {},
  135. },
  136. },
  137. setup(props) {
  138. console.log(props.listData);
  139. const { proxy } = getCurrentInstance();
  140. const selectValue = ref(null);
  141. const currentPage = ref(1);
  142. const pageSize = ref(10);
  143. const small = ref(false);
  144. const background = ref(false);
  145. const disabled = ref(false);
  146. const tableRowEditId = ref(0);
  147. const tableColumnEditIndex = ref(0);
  148. //图片平铺
  149. const fit = ref("fill");
  150. //对日期进行截取
  151. function repString(val) {
  152. return val.substr(0, 10);
  153. }
  154. const blurUnitInput = (row: any, column: any) => {
  155. console.log(row, column);
  156. tableRowEditId.value = null;
  157. tableColumnEditIndex.value = null;
  158. //在此处调接口传数据
  159. };
  160. const tableRowStyle = ({ row }) => {
  161. let arr = [];
  162. if (selectValue.value !== null) {
  163. selectValue.value.filter((item, index) => {
  164. arr.push(item.id);
  165. });
  166. }
  167. for (var i = 0; i <= arr.length; i++) {
  168. if (arr[i] == row.id) {
  169. return { backgroundColor: "#ebf5ff !important" };
  170. }
  171. }
  172. };
  173. // 点击其他位置也选中当前行
  174. const clickRow = (row) => {
  175. console.log(row);
  176. proxy.$refs.table.toggleRowSelection(row, undefined);
  177. };
  178. function handleSizeChange(val) {
  179. console.log(val);
  180. }
  181. function handleCurrentChange(val) {
  182. console.log(val);
  183. }
  184. // 多选框选中数据
  185. function handleSelectionChange(selection) {
  186. console.log(selection);
  187. selectValue.value = selection;
  188. }
  189. const showUnitInput = (row: any, column: any) => {
  190. // console.log('row', row)
  191. // console.log('column', column)
  192. //赋值给定义的变量
  193. tableRowEditId.value = row.id; //确定点击的单元格在哪行 如果数据中有ID可以用ID判断,没有可以使用其他值判断,只要能确定是哪一行即可
  194. tableColumnEditIndex.value = column.id; //确定点击的单元格在哪列
  195. };
  196. return {
  197. repString,
  198. tableRowStyle,
  199. clickRow,
  200. handleSelectionChange,
  201. selectValue,
  202. currentPage,
  203. pageSize,
  204. handleSizeChange,
  205. handleCurrentChange,
  206. small,
  207. background,
  208. disabled,
  209. blurUnitInput,
  210. tableRowEditId,
  211. tableColumnEditIndex,
  212. fit,
  213. showUnitInput,
  214. };
  215. },
  216. };
  217. </script>
  218. <style lang="scss">
  219. .ipt {
  220. border: 0px;
  221. }
  222. </style>

组件使用tableDemo.vue:

  1. <template>
  2. <div class="app-container">
  3. <Ltable
  4. :tableData="list"
  5. :tableHeader="tableHeader"
  6. :listLoading="listLoading"
  7. :maxHeight="maxHeight"
  8. :listData="listData"
  9. ></Ltable>
  10. </div>
  11. </template>
  12. <script lang="ts" setup>
  13. import Ltable from "@/components/commonTable/index.vue";
  14. import { ref, reactive, nextTick, onMounted, toRefs } from "vue";
  15. import { useRouter } from "vue-router";
  16. import { ElMessage } from "element-plus";
  17. const router = useRouter();
  18. const state = reactive({
  19. // 模拟数据
  20. list: [
  21. {
  22. id: "123456",
  23. votethemeTitle: "dh",
  24. userName: "yp",
  25. votethemeStart: "2024-01-01",
  26. votethemeEnd: "2024-01-02",
  27. worksCount: "带钢",
  28. image:
  29. "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
  30. votethemeStatus: "1",
  31. },
  32. {
  33. id: "1234567",
  34. votethemeTitle: "dh",
  35. userName: "yp",
  36. votethemeStart: "2024-01-01",
  37. votethemeEnd: "2024-01-02",
  38. worksCount: "带钢",
  39. image:
  40. "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
  41. votethemeStatus: "3",
  42. },
  43. {
  44. id: "12345678",
  45. votethemeTitle: "dh",
  46. userName: "yp",
  47. votethemeStart: "2024-01-01",
  48. votethemeEnd: "2024-01-02",
  49. worksCount: "带钢",
  50. image:
  51. "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
  52. votethemeStatus: "2",
  53. },
  54. ],
  55. page: {},
  56. listLoading: false,
  57. // 表头
  58. tableHeader: [
  59. {
  60. prop: "id",
  61. label: "编号",
  62. minWidth: "50px",
  63. },
  64. {
  65. prop: "votethemeTitle",
  66. label: "主题名称",
  67. minWidth: "150px",
  68. type: "edit",
  69. },
  70. {
  71. prop: "userName",
  72. label: "发布人",
  73. minWidth: "80px",
  74. },
  75. {
  76. prop: ["votethemeStart", "votethemeEnd"],
  77. label: "活动时间",
  78. minWidth: "210px",
  79. isDate: true,
  80. },
  81. {
  82. prop: "worksCount",
  83. label: "参与作品",
  84. minWidth: "80px",
  85. },
  86. {
  87. prop: "image",
  88. label: "图片",
  89. minWidth: "120px",
  90. type: "img",
  91. },
  92. {
  93. prop: "votethemeStatus",
  94. label: "状态",
  95. minWidth: "80px",
  96. isline: true,
  97. type: "dic",
  98. },
  99. {
  100. prop: "btn",
  101. label: "操作",
  102. minWidth: "120px",
  103. btn: [
  104. {
  105. name: "查看",
  106. func: handleLook,
  107. },
  108. {
  109. name: "编辑",
  110. func: handleEdit,
  111. },
  112. ],
  113. },
  114. ],
  115. maxHeight: "calc(100vh - 322px)",
  116. });
  117. // 模拟数据字典数据
  118. const votethemeStatus = ref([
  119. { key: 1, value: "未开始", type: "" },
  120. { key: 2, value: "进行中", type: "primary" },
  121. { key: 3, value: "已结束", type: "danger" },
  122. ]);
  123. let listData = reactive({});
  124. listData["votethemeStatus"] = votethemeStatus;
  125. const { list, page, listLoading, tableHeader, maxHeight } = toRefs(state);
  126. onMounted(() => {
  127. // fetchData()
  128. });
  129. // 按钮事件
  130. function handleEdit(index, row) {
  131. console.log(row);
  132. }
  133. function handleLook(index, row) {
  134. router.push({
  135. path: "detail?id=" + row.id,
  136. });
  137. }
  138. </script>
  139. <style></style>

 

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