iview的表格实现单元格行编辑功能

iview的表格实现单元格行编辑功能

截图:
请添加图片描述
实现功能:

  • 可分页批量编辑并保存

  • 输入框支持上下键换行编辑

实现方式

使用插槽

<template>
  <layout :footerHeight="0">
    <template #Opration>
      <div
        style="
          width: 100%;
          height: 100%;
          display: flex;
          justify-content: flex-end;
          align-items: center;
        "
      >
        <Button size="small" @click="cancelBatchEdit()" style="margin: 0 5px" v-if="age_is_edit"
          >取消批量编辑</Button
        >
        <Button type="primary" size="small" @click="batchEdit()" style="margin: 0 5px" v-else
          >批量编辑</Button
        >
        <Button type="primary" size="small" @click="batchSave()" style="margin: 0 5px"
          >批量保存</Button
        >
      </div>
    </template>
    <template #main>
      <div
        style="
          width: 100%;
          height: 100%;
          display: flex;
          flex-direction: column;
          justify-content: space-between;
        "
      >
        <div style="height: 92%; overflow: auto">
          <Table
            :data="results"
            style="display: flex;height: 100%;"
            :columns="[
              {
                title: '序号',
                name: '序号',
                key: 'index',
                width: 90,
              },
              {
                title: '年龄',
                name: '年龄',
                key: 'age',
                isShow: 1,
                width: 200,
                resizable: 1,
                sortable: 1,
                slot: 'edit',
              },
              {
                title: '备注',
                name: '备注',
                key: 'remark',
                isShow: 1,
                width: 200,
                resizable: 1,
                sortable: 1,
              },
            ]"
          >
            <template #edit="{ row, column }">
              <div
				:class="column.key"
                style="
                  cursor: pointer;
                  min-width: 120px;
                  min-height: 48px;
                  display: flex;
                  align-items: center;
                "
              >
                <template v-if="age_is_edit">
                  <YsInput
					@keyup.native="handleKeyup($event, row, column.key)"
                    v-model="row[column.key]"
                    @on-blur="changeValue(row, column, row[column.key], row._index)"
                  />
                </template>
                <template v-else>
                  <span>{{ row[column.key] }}</span>
                </template>
              </div>
            </template>
          </Table>
        </div>
        <div
          style="
            width: 100%;
            height: 8%;
            padding: 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
          "
        >
          <span>共 {{ page.total }} 条</span>
          <Page
            :current.sync="args.page_para.page_index"
            :total="page.total"
            :page-size-opts="pageSizeOpts"
            show-sizer
            @on-page-size-change="handlePageSizeChange"
            @on-change="handlePageChange"
          />
        </div>
      </div>
    </template>
  </layout>
</template>

<script>
import { differenceWith, isEqual, cloneDeep } from "lodash";
export default {
  data() {
    return {
      age_is_edit: false,
      pageSizeOpts: [10, 20, 30, 40],
      args: {
        conditions: {
        },
        page_para: {
          page_index: 1,
          page_size: 10,
        },
      },
      page: {
        total: 0,
        currnt: 1,
        pageSize: 10,
      },
      results: [],
      originalResults: [],
      editResults: [],
    };
  },
  created() {
    this.getData();
  },
  methods: {
    cancelBatchEdit() {
      this.age_is_edit = false;
      this.args.page_para.page_index = 1;
      this.getData(1);
    },
    batchEdit() {
      this.age_is_edit = true;
    },
    async batchSave() {
      let data = differenceWith(this.editResults, this.originalResults, isEqual);
      data = cloneDeep(data);
      let reg = /^[0-9]*[1-9][0-9]*$/;
      this.batchSaveService.args.t_list = [];
      if (data?.length) {
        for (let i in data) {
          if (data[i].age && !reg.test(data[i].age)) {
            this.$Message.warning(`第${data[i].index}行的年龄请输入数字!`);
            return false;
          }
        }
        this.age_is_edit = false;
        await this.$http(data);
        this.$Nessage.success("操作成功!");
        this.args.page_para.page_index = 1;
        this.getData(1);
      } else {
        this.$Message.info("无操作数据!");
      }
    },
		handleKeyup(event, row, key) {
			// ↑
			if (event.keyCode === 38) {
				if (row._index > 0) {
					this.changeCurrentRow(row, key, "-");
				}
			}
			// ↓
			if (event.keyCode === 40) {
				if (row._index + 2 <= this.page.pageSize) {
					this.changeCurrentRow(row, key, "+");
				}
			}
		},
		changeCurrentRow(row, key, type) {
			let curIndex = row._index;
			if (type === "+") {
				curIndex = row._index + 1;
			} else {
				curIndex = row._index - 1;
			}
			this.$set(this.results, row._index, row);
			let changeRow = this.results[curIndex];
			this.$set(this.results, curIndex, changeRow);
			this.$nextTick(() => {
				let e = document.querySelectorAll(`.${key}`)[curIndex];
				e.querySelector('input').focus();
			});
		},
    async getData(flag = 0) {
      if (flag === 1) {
        this.editResults = [];
        this.originalResults = [];
      }
      let res = await this.$http({});
      this.page.total = res.total;
      let [pageIndex, pageSize] = [this.args.page_para.page_index, this.args.page_para.page_size];
      if (res.total > 0) {
        res.result.forEach((item, index) => {
          // 序号
          this.$set(item, "index", ((pageIndex - 1) * pageSize) + index + 1);
          this.$set(item, "age_is_edit", false);
        });
      }
      if (this.editResults.length < pageIndex * pageSize) {
        // 当前表格显示数据
        this.results = res.result;
        // 编辑数据
        this.editResults.push(...res.result);
        // 原始数据
        this.originalResults.push(...cloneDeep(res.result));
      } else {
        this.results = this.editResults.slice((pageIndex - 1) * pageSize, pageIndex * pageSize);
      }
    },
    changeValue(row, column, val, index) {
      if (val) {
        if (!/^[0-9]*[1-9][0-9]*$/.test(val)) {
          this.$Message.warning("请输入数字!");
          this.results[index][column.key] = val;
        } else {
          this.results[index][column.key] = parseFloat(val);
        }
      }
    },
  },
};
</script>

使用render函数

<template>
  <layout>
    <template #main>
      <div
        style="
          width: 100%;
          height: 100%;
          display: flex;
          flex-direction: column;
          justify-content: space-between;
        "
      >
        <div style="height: 92%; overflow: auto">
          <Table
            :data="results"
            style="display: flex;height: 100%;"
            :columns="[
              {
                title: '序号',
                name: '序号',
                key: 'index',
                width: 90,
              },
              {
                title: '年龄',
                name: '年龄',
                key: 'age',
                isShow: 1,
                width: 200,
                resizable: 1,
                sortable: 1,
                render: render,
              },
              {
                title: '备注',
                name: '备注',
                key: 'remark',
                isShow: 1,
                width: 200,
                resizable: 1,
                sortable: 1,
              },
            ]"
          >
          </Table>
        </div>
        <div
          style="
            width: 100%;
            height: 8%;
            padding: 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
          "
        >
          <span>共 {{ page.total }} 条</span>
          <Page
            :current.sync="args.page_para.page_index"
            :total="page.total"
            :page-size-opts="pageSizeOpts"
            show-sizer
            @on-page-size-change="handlePageSizeChange"
            @on-change="handlePageChange"
          />
        </div>
      </div>
    </template>
  </layout>
</template>

<script>
export default {
  data() {
    return {
      age_is_edit: false,
      pageSizeOpts: [10, 20, 30, 40],
      args: {
        conditions: {
        },
        page_para: {
          page_index: 1,
          page_size: 10,
        },
      },
      page: {
        total: 0,
        currnt: 1,
        pageSize: 10,
      },
      results: [],
    };
  },
  created() {
    this.getData();
  },
  methods: {
    render(h, { row, column, index }) {
      return (
        <div 
          style="cursor: pointer"
          vOn:click={(e) => {
          this.changeIndex(e, index, row)
        }}>
          {!row.nameIsEdit ? (
            <span>{row[column.key]}</span>
          ) : (
            <Input vModel={row[column.key]} vOn:on-blur={() => this.changeValue(row, column, row[column.key], index)} />
          )}
        </div>
      )
    },
    async getData(flag = 0) {
      let res = await this.$http({});
      if (res.total > 0) {
        res.result.forEach((item) => {
          this.$set(item, 'nameIsEdit', false);
        });
      }
     this.results = res.result;
    },
    changeValue(row, column, val, index) {
      this.$set(row, 'nameIsEdit', false);
      results[index][column.key] = val
    },
    changeIndex(e, index, row) {
      this.flag = false;
      this.$set(row, 'nameIsEdit', true);
      //实现点击后输入框自动聚焦
      this.$nextTick(() => {
        e.currentTarget.getElementsByTagName("input")[0].focus();
      });
    },
  },
};
</script>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在iview table的编辑实现文件上传,您可以按照以下步骤进操作: 1. 首先,在您的iview table中创建一个列,用于显示文件上传的按钮。您可以使用`slot-scope`来自定义列的内容,示例如下: ```html <template slot-scope="{ row }"> <Upload action="/your-upload-url" :on-success="handleSuccess" :on-error="handleError" :before-upload="beforeUpload" > <Button icon="ios-cloud-upload-outline">上传文件</Button> </Upload> </template> ``` 2. 在data中定义一个变量,用于存储上传成功后的文件链接。例如: ```javascript data() { return { fileList: [] }; }, ``` 3. 实现上传成功和失败的回调函数`handleSuccess`和`handleError`,以及上传前的钩子函数`beforeUpload`。示例如下: ```javascript methods: { handleSuccess(response, file, fileList) { // 上传成功后的处理逻辑 // 可以将文件链接存储到fileList中或者其他地方 this.fileList = fileList; }, handleError(error, file, fileList) { // 上传失败后的处理逻辑 console.log('上传失败:', error); }, beforeUpload(file) { // 可以在这里对上传的文件进限制,比如大小、类型等 // 返回 false 可以阻止上传 console.log('准备上传:', file); } }, ``` 4. 最后,在您的iview table中的列配置中,将刚刚创建的列添加到需要编辑中。示例如下: ```html <Table :data="yourData"> <Table-column prop="yourProp" label="您的属性"></Table-column> <Table-column label="文件上传"> <template slot-scope="{ row }"> <!-- 文件上传列 --> </template> </Table-column> <!-- 其他列配置 --> </Table> ``` 通过以上步骤,您就可以在iview table的编辑实现文件上传功能了。当用户点击上传按钮时,会触发文件上传操作,并在上传成功后将文件链接存储到`fileList`中。您可以根据实际需求进进一步处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值