近期项目上遇到的一些功能;字符串比对(diffjs)、打印功能(printJS)、两端布局中间可拖拽功能实现

(买了辆公路车,五一从北京出发骑行了一趟天津,10h,150km。很累但很爽,哈哈。路上看到了很多骑友,而且居然还有骑共享单车去天津的!看样子像是学生,实在佩服。)

前言

也是好久没更新文章了,一直说要学习来着,主要是下班时间和周末经不住游戏和短视频小姐姐的'诱惑',常常沉迷于二者,还是自律性太差了,以后争取每天学习一段时间。话说,jym每天下班都会干什么?不会吧,不会吧,不会都在内卷吧,欢迎评论区留言。

ok,言归正传,近期项目组开了一个新项目,用的是vue3+vite的框架,近期项目也是快完工了,正好抽时间总结一下,遇到的一些需求和解决方法。如果jym近期遇到了或者以后可能会遇到相似的需求,可以借鉴参考下。

字符串比对(diffjs)

先展示一下最终的效果

我们这个项目做的是一个流程,就是有一些数据,一些人可以去更改这些数据,但是更改完数据以后需要发起流程去审批,通过以后这条数据才会真正被修改。

那么审批人就需要知道发起人都修改了哪些数据,这就有了如图所示的需求。更改后的数据需要和原数据去比对,如果是新增的数据需要标红,删除的数据需要标红加删除线。

我这边用到了diffjs这个插件。数据上,后端返回了两个对象,oldData和newData,我们需要拿到两个data里相同字段的值进行比对,返回比对后的结果,就是用span标签包裹起来,然后用v-html去渲染。

代码实现:

js 复制代码
import * as Diff from 'diff';

// 比较两个字符串,变化的标红,删除的加删除线
export const diffFun = (oldValue:string, newValue:string) => {
  const testStr = Diff.diffChars(oldValue, newValue);
  let str = '';
  testStr.forEach((item:any) => {
    if (item.added) {
      str = `${str}<span style="color:red;">${item.value}</span>`;
    } else if (item.removed) {
      str = `${str}<span style="color:red;text-decoration: line-through;">${item.value}</span>`;
    } else {
      str = `${str}${item.value}`;
    }
  });
  return str;
};

打印(printJS)

打印功能使用到了,printJS这个插件,printable是要打印的数据,field是要打印数据的字段名,displayName是要打印数据的表头名,columnSize可以设置列宽,但是会挤压最后一列。

js 复制代码
import printJS from 'print-js';
// 打印函数
const printFun = async () => {
  printJS({
    printable: [...tableData], // 要打印的数据
    properties: [
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称', columnSize: '20%' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' }
    ],
    type: 'json',
    scanStyles: false, // 不适用默认样式
    repeatTableHeader: false, // 打印json表头只显示在第一页
    gridHeaderStyle: 'border: 1px solid #909399;text-align:center;', // 表格头样式
    gridStyle: 'border: 1px solid #909399; text-align:center;', // 表哥体样式
    style: '@page{size:auto;margin: 0cm 1cm 0cm 1cm;}'// 去除页眉页脚
    // style:'@media print{@page {size:landscape}}' //横行打印
  });
};

两端布局中间可拖拽功能实现

相关代码逻辑:

js 复制代码
<template>
    <div :style="{height:that.height}" class="box">
    <el-row :gutter="10">
    <div style="width: 20%" class="left">
      <div class="resize" title="左右侧边栏">⋮</div>
      <el-card :style="{height:treeHeight,overflow: 'auto'}">
        left
      </el-card>
    </div>
    <div style="width: 80%;" class="right">
      <el-card :style="{height:treeHeight,overflow: 'auto'}">
        right
      </el-card>
    </div>
    </el-row>
    </div>
</template>

<script>
// 左右拖动事件
function dragControllerLR () {
  const resize = document.getElementsByClassName('resize') as any;
  const left = document.getElementsByClassName('left') as any;
  const right = document.getElementsByClassName('right') as any;
  const box = document.getElementsByClassName('box') as any;
  for (let i = 0; i < resize.length; i++) {
    resize[i].onmousedown = function (e:any) {
    // 颜色改变提醒
      resize[i].style.background = '#818181';
      const startX = e.clientX;
      resize[i].left = resize[i].offsetLeft;

      // 鼠标拖动事件
      document.onmousemove = function (e) {
        const endX = e.clientX;
        let moveLen = resize[i].left + (endX - startX); // (endx-startx)=移动的距离。resize[0].left+移动的距离=左边区域最后的宽度
        const maxT = box[0].clientWidth - resize[i].offsetWidth; // 容器宽度 - 左边区域的宽度 = 右边区域的宽度

        if (moveLen < 50) moveLen = 50; // 左边区域的最小宽度为50px
        if (moveLen > maxT - 150) moveLen = maxT - 150; // 右边区域最小宽度为150px

        resize[i].style.left = moveLen; // 设置左侧区域的宽度

        for (let j = 0; j < left.length; j++) {
          left[j].style.width = moveLen + 'px';
          right[0].style.width = box[0].clientWidth - moveLen + 'px';
        }
      };

      // 鼠标松开事件
      document.onmouseup = function (evt) {
      // 颜色恢复
        resize[i].style.background = '#d6d6d6';
        document.onmousemove = null;
        document.onmouseup = null;
        resize[i].releaseCapture && resize[i].releaseCapture(); // 当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
      };
      resize[i].setCapture && resize[i].setCapture(); // 该函数在属于当前线程的指定窗口里设置鼠标捕获
    };
  };
}

// 在组件挂载完成后,调用dragControllerLR函数
onMounted(() => {
  dragControllerLR();
});
</script>

<style scoped>
.box{
  width: 100%;
}
  /* 拖拽区div样式 */
  .resize {
    cursor: w-resize;
    float: right;
    position: relative;
    top: 45%;
    background-color: #d6d6d6;
    border-radius: 5px;
    margin-top: -10px;
    width: 10px;
    height: 50px;
    background-size: cover;
    background-position: center;
    font-size: 32px;
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
  }
</style>
最后放上几张骑行时拍的照片
相关推荐
雪碧聊技术18 分钟前
深入解析Vue中v-model的双向绑定实现原理
前端·javascript·vue.js·v-model
快起来别睡了19 分钟前
手写 Ajax 与 Promise:从底层原理到实际应用
前端
打不着的大喇叭1 小时前
uniapp的光标跟随和打字机效果
前端·javascript·uni-app
无我Code1 小时前
2025----前端个人年中总结
前端·年终总结·创业
程序猿阿伟1 小时前
《前端路由重构:解锁多语言交互的底层逻辑》
前端·重构
Sun_light1 小时前
6个你必须掌握的「React Hooks」实用技巧✨
前端·javascript·react.js
爱学习的茄子2 小时前
深度解析JavaScript中的call方法实现:从原理到手写实现的完整指南
前端·javascript·面试
莫空00002 小时前
Vue组件通信方式详解
前端·面试
呆呆的心2 小时前
揭秘 CSS 伪元素:不用加标签也能玩转出花的界面技巧 ✨
前端·css·html
百锦再2 小时前
重新学习Vue中的按键监听和鼠标监听
javascript·vue.js·vue·计算机外设·click·up·down