vue+elementui自定义指令实现滚动条联动文件对比

    最近项目有个需求,就是需要个文件对比的功能,后端直接给我丢了一串60k的数据,这个是原数据,然后给我现数据在原数据的基础上发生
的改变,包括新增、删除、修改。需要在左边的框里显示原数据,右边显示现在的数据,就是一个文件对比的功能,要求新增、删除、修改的
内容用不同的颜色标注出来。

1.处理数据

		由于数据比较庞大,后端不可能把现数据和原数据都给我,所以我需要把现数据在原数据的基础上处理好。后端给我的是个json对象,
我需要循环遍历先处理修改,因为我展现数据时用的时index,所以这时候处理更改后的索引很重要,不能先添加数据,先添加数据两个数
据就会不整齐,处理起来也比较麻烦。先处理修改比较简单,因为修改就是在原数据的基础上进行更改,索引是不会变的。我们需要循环
遍历数据,在需要修改的地方修改数据,这时顺带把修改数据的索引记下来,方便后面展现数据时进行标注颜色,修改标注为黄色。
		然后,我们需要处理删除,删除的时候也需要遍历原数据,在删除数据的时候,删除数据的处理,我不是完全的删除,而是变相的删
除,就是把原数据以自己设计的标识码进行修改,当然也要保证不会影响潜在数据。这时处理标注就简单多了,只需要知道索引原数据与
现数据的遍历染色是一样的,删除的原数据与现数据都标注为红色。
		最后就是处理新增,新增我一般会利用数据的类型的优势,把新增数据push进数组中,这时新增的数据默认就在最后,处理新增标注
时只需要知道原数据的最大索引,大于这个索引值现数据全部标注为绿色,原数据不需要改变。

2.自定义指令实现对比


template代码:
<el-dialog
        :visible.sync="ExResultView"
        :before-close="ExResultClose"
        title="核查详情"
        width="60%"
      >
        <el-row style="margin: 10px;">
          <span
            style="background-color: #42b983;display: inline-block;width: 10px;height: 10px;margin: 0 10px 0 10px;"
          />
          <span>新增</span>
          <span
            style="background-color: rgb(247, 120, 88);display: inline-block;width: 10px;height: 10px;margin: 0 10px 0 10px;"
          />
          <span>删除</span>
          <span
            style="background-color: #F19E04;display: inline-block;width: 10px;height: 10px;margin: 0 10px 0 10px;"
          />
          <span>更新</span>
        </el-row>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-card shadow="hover">
              <el-table
                v-tablelinkwork="tableLoadMore1"
                ref="Extable1"
                :data="ExOldValue"
                :row-class-name="tableRowClassName"
                height="650"
                style="width: 100%"
              >
                <el-table-column :index="indexMethod" type="index" width="80" />
                <el-table-column :label="croldBatime" prop="data" />
              </el-table>
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card shadow="hover">
              <el-table
                v-tablelinkwork="tableLoadMore2"
                ref="Extable2"
                :data="ExNewValue"
                :row-class-name="tableRowClass"
                style="width: 100%"
                height="650"
              >
                <el-table-column :index="indexMethod" type="index" width="80" />
                <el-table-column :label="crnewBatime" prop="data" />
              </el-table>
            </el-card>
          </el-col>
        </el-row>
        <span slot="footer" class="dialog-footer">
          <el-button @click="ExResultView = false">取 消</el-button>
          <el-button type="primary" @click="downEx">下 载</el-button>
        </span>
</el-dialog>
注册指令:
directives: {
    // 这里是自定义指令
    tablelinkwork: {
      bind: function(el, binding) {
        // bind钩子函数,当它与元素绑定的时候就会执行

        const SELECTWRAP_DOM = el.querySelector('.el-table__body-wrapper')

        SELECTWRAP_DOM.addEventListener('scroll', function() {
          clearTimeout(t)
          const t = setTimeout(function() {
            binding.value()
          }, 150)
        })
      }
    }
  },
data数据:
data(){
	return {
		ExResultView: false,
		ExNewValue: [], // 数据
        ExOldValue: [],
        Loading: false, // loading样式
      	uindex: [], // 修改标注索引数组
      	delindex: [], // 删除标注索引数组
      	addindex: [], // 新增标注索引数组
      	croldBatime: '', // 时间戳
      	crnewBatime: '',
	}
}
方法:
method: {
	tableLoadMore1() {
      const tab1 = this.$refs['Extable1'].bodyWrapper
      const tab2 = this.$refs['Extable2'].bodyWrapper
      this.$nextTick(() => {
        tab2.scrollTop = tab1.scrollTop
      })
    },
    tableLoadMore2() {
      const tab1 = this.$refs['Extable1'].bodyWrapper
      const tab2 = this.$refs['Extable2'].bodyWrapper
      this.$nextTick(() => {
        tab1.scrollTop = tab2.scrollTop
      })
    },
    tableRowClassName({ rowIndex }) {
      if (this.uindex.includes(rowIndex)) {
        return 'update-row'
      }
      if (this.delindex.includes(rowIndex)) {
        return 'delete-row'
      }
    },
    tableRowClass({ rowIndex }) {
      if (rowIndex > this.addindex) {
        return 'add-row'
      } else {
        if (this.uindex.includes(rowIndex)) {
          return 'update-row'
        }
        if (this.delindex.includes(rowIndex)) {
          return 'delete-row'
        }
      }
    },
    indexMethod(index) {
      return index + 1
    },
    downEx() {
      service.downloadEx(this.subex_forms).then(res => {
        this.download(res)
      })
    },
    // 下载excel数据表格
    download(data) {
      if (!data) {
        return
      }
      var blob = new Blob([data], {
        type:
          'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
      })
      var url = window.URL.createObjectURL(blob)
      var aLink = document.createElement('a')
      aLink.style.display = 'none'
      aLink.download = '基线核查结果.xls'
      aLink.href = url
      document.body.appendChild(aLink)
      aLink.click()
      document.body.removeChild(aLink) // 下载完成移除元素
      window.URL.revokeObjectURL(url)
    },
    
}
style样式:
.el-table .add-row {
  background: #42b983;
}
.el-table .update-row {
  background: #f19e04;
}
.el-table .delete-row {
  background: rgb(247, 120, 88);
}
	这里,数据处理部分的代码,我没有展现主要是没有什么利用价值,每个需求所需要的数据都不一样,这里就不在展示,
你如果使用只需要把数据处理成elementui表格数据的规范就可以了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现文件上传需要完成以下几个步骤: 1. 在前端页面添加上传文件的表单,并绑定上传事件,将文件上传到后端。 2. 在后端接收前端上传的文件,并保存到服务器上。 下面是一个简单的示例,演示如何使用 Spring Boot + Vue.js + ElementUI 实现文件上传的功能。 前端代码: ```html <template> <div> <el-upload class="upload-demo" ref="upload" :action="uploadUrl" :on-success="handleSuccess" :before-upload="beforeUpload" :file-list="fileList"> <el-button size="small" type="primary">点击上传</el-button> <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> </el-upload> </div> </template> <script> export default { data() { return { uploadUrl: "/upload", fileList: [] }; }, methods: { // 上传前的钩子函数 beforeUpload(file) { const isJPG = file.type === "image/jpeg" || file.type === "image/png"; const isLt500K = file.size / 1024 < 500; if (!isJPG) { this.$message.error("上传头像图片只能是 JPG/PNG 格式!"); } if (!isLt500K) { this.$message.error("上传头像图片大小不能超过 500KB!"); } return isJPG && isLt500K; }, // 上传成功的回调函数 handleSuccess(response, file, fileList) { this.fileList = fileList; this.$emit("upload-success", response); } } }; </script> ``` 在上面的代码中,我们使用了 ElementUI 的 Upload 组件,将上传文件的表单渲染到页面上。同时,我们还绑定了 beforeUpload 和 handleSuccess 两个事件,用于上传前的校验和上传成功后的回调。 注意:在使用 beforeUpload 钩子函数时,需要返回一个布尔值,表示是否允许上传。如果返回 false,上传将会被终止。 后端代码: ```java @RestController public class FileUploadController { @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) throws Exception { if (file.isEmpty()) { return "上传文件为空!"; } // 获取文件名 String fileName = file.getOriginalFilename(); // 获取文件的后缀名 String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 设置文件存储路径 String filePath = "/tmp/"; // 重新生成文件名 fileName = UUID.randomUUID() + suffixName; // 创建文件对象 File dest = new File(filePath + fileName); // 检测是否存在目录 if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } // 保存文件 file.transferTo(dest); return "文件上传成功!"; } } ``` 在上面的代码中,我们使用了 Spring Boot 的 @PostMapping 注解,将上传文件的接口地址映射到 /upload 路径上。同时,我们还使用了 MultipartFile 类型的参数来接收前端上传的文件。 在接收到文件后,我们首先判断文件是否为空。如果不为空,我们通过 MultipartFile 类型的方法获取文件名和后缀名,并将文件存储到指定的路径下。最后,我们返回一个字符串,表示上传成功。 需要注意的是,在保存文件时,我们使用了 transferTo 方法。该方法会将上传文件保存到指定的路径下,并自动关闭文件流。同时,我们还判断了目录是否存在,如果不存在,就创建一个新的目录。 综上所述,通过以上的代码,我们可以实现 Spring Boot + Vue.js + ElementUI文件上传功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值