Vxe-Table的各种坑,以及避坑指南(需要补充的请留言)_小狼子丶的博客-程序员ITS301_vxe-table

技术标签: web前端  Vxe-Table  elementui  前端  element-plus  js  javascript  

背景:

由于公司要开发erp,采用了element-plus做为UI基础框架,但是回想往事点点滴滴,element-ui表格的种种表现令人痛心,于是跟leader商量之后决定使用Vxe-Table做表格插件,虽然element-plus在表格上也在大力优化,但就目前来看可用度确实不高,刚出了一个虚拟滚动,但看上去确实让人有点心急。。。

开发阶段遇到的各种问题

全局size的问题

有点扯犊子的事,我element-plus要做全局的size修改,那就意味着我的表格也要做全局的size修改,庆幸的是它有自带的全局size配置,配置方法也很简单,在setup方法中设置即可,配合vuex、本地存储(包括cookie),还有模有样的可以搞一搞,不幸的是,这特么size跟element-plus的size规则天差地别,虽然可以通过修改变量去规避这个问题,但是成本属实有点高。而且element-plus的为large、default、small,但是Vxe-Table的为下面是medium、small、mini还需要做判断,杂七杂八,有点小恶心。下面附上代码。

import 'xe-utils'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
//引入font-awesome
import 'font-awesome/css/font-awesome.css'
import { localAppSizeKey } from '@/store/modules/settings/index'

VXETable.setup({
  size: formatSize(localStorage.getItem(localAppSizeKey) || 'default') as any
})

export default function (app: any) {
  app.use(VXETable)
  // 给 vue 实例挂载内部对象,例如:
  // app.config.globalProperties.$XModal = VXETable.modal
  // app.config.globalProperties.$XPrint = VXETable.print
  // app.config.globalProperties.$XSaveFile = VXETable.saveFile
  // app.config.globalProperties.$XReadFile = VXETable.readFile
}

/**
 * 解析element-plus的全局size
 * @param size
 * @returns
 */
function formatSize(size: null | undefined | string) {
  let resSize = 'small'
  switch (size) {
    case 'large':
      resSize = 'medium'
      break
    case 'default':
      resSize = 'small'
      break
    case 'small':
      resSize = 'mini'
      break
  }
  return resSize
}

size是存在localStorage里面的,设置一次,更新一次值,我这里就很简单粗暴了,全局设置element-plus的size然后通过format方法解析,存入本地存储,然后刷新页面,啊哈哈哈哈,问就是还不知道咋搞,有人知道的麻烦私一个,解决这个问题。

按钮的问题

说真的,我很能理解作者的设计模式,我也很佩服作者的代码功底,毕竟我只是一个使用者,但是但是,你自己开发一套按钮什么的,能不能走点心嘛,按钮中的文字居然不能垂直居中。大哥这都啥年代了哎,附上我处理按钮垂直居中的代码

.vxe-button.type--button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

简单粗暴,flex解决,有问题再解决

合并单元格的问题

单元格合并的按照官网提供的案例,第一次使用了spanMethod方法,那时候数据量少,没有开启虚拟滚动,后来数据量大了,测试滚动了一下叫了一声,我头皮一麻就知道出问题了,结果我看到官网上赫然写着,不支持虚拟滚动,哎~~ 我用这个表格不就是冲着虚拟滚动来的吗?再找解决方案把,后来决定还是用【mergeCells】去解决这个问题,解决思路就是,根据需求,合并固定的列,然后在数据中查询最近的相同数据(后端已排好序),生成要合并的数据,然后赋值到gridOptions对象上面,具体实现如下:

proxyConfig: {
    seq: true,
    sort: true,
    filter: true,
    form: true,
    props: {
      result: 'data.data',
      total: 'data.totalCount'
    },
    ajax: {
      query: async ({ page, form }) => {
        const { pageSize: size, currentPage } = page
        const paging = { size, page: currentPage }
        const queryParams: any = Object.assign({ isOdm: 1 }, paging, form)
        const response = await queryList(queryParams)
        // 合并单元格选项
        let mergeCells: any[] = []
        mergeCells = generateMergeCells(
          response.data.data,
          'spuName',
          [2, 3, 4, 5, 6, 7, 8]
        )
        gridOptions.mergeCells = mergeCells
        return response
      }
    }
  },

这时候第一页可以分页了,但是跳转页面后,发现问题了,第二页分页居然错乱?后面的全乱了!!大爷的。为此谷歌百度都查了,结果还是没有解决方案。后来突发奇想,每次分页我reload一下会不会好点,结果还真就行了,其实就是在前面代码中加入一行代码:xGrid.value.reloadData(response.data.data)

proxyConfig: {
    seq: true,
    sort: true,
    filter: true,
    form: true,
    props: {
      result: 'data.data',
      total: 'data.totalCount'
    },
    ajax: {
      query: async ({ page, form }) => {
        const { pageSize: size, currentPage } = page
        const paging = { size, page: currentPage }
        const queryParams: any = Object.assign({ isOdm: 1 }, paging, form)
        const response = await queryList(queryParams)
        // 合并单元格选项
        let mergeCells: any[] = []
        mergeCells = generateMergeCells(
          response.data.data,
          'spuName',
          [2, 3, 4, 5, 6, 7, 8]
        )
        gridOptions.mergeCells = mergeCells
        xGrid.value.reloadData(response.data.data)
        return response
      }
    }
  },

芜湖~~,解决!附上动态生成mergeCells的代码

// 生成合并单元格数据
export const generateMergeCells = (
  data: any[],
  key: string,
  cols: number[]
) => {
  if (data.length === 0) return []
  let pointer: number = 0
  let total: number = 0
  let curKeyValue: any = data[0][key]
  const result = data.reduce((acc: any[], cur: any, index: number) => {
    const val = cur[key]
    let mergeData: any = []
    if (val !== curKeyValue) {
      // 生成合并数据
      if (total > 1) {
        mergeData = generateCells(cols, pointer, total)
      }
      curKeyValue = val
      pointer = index // 指针index赋值
      total = 1
    } else {
      total += 1
      if (index === data.length - 1) {
        mergeData = generateCells(cols, pointer, total)
      }
    }
    acc.push(...mergeData)
    return acc
  }, [])
  return result
}

export const generateCells = (
  cols: number[],
  rowIndex: number,
  rowspan: number
) => {
  return cols.map((col: number) => {
    return {
      row: rowIndex,
      col,
      rowspan,
      colspan: 1
    }
  })
}

reload和load的问题

我实在搞不懂为什么每次reload和load要传参数进去,而却重置和查询这种按钮的方法没有抛出来以供调用。

但是也可以解决,作者抛出了很多方法,但是说明文档里面没有...,具体可以参照node_modules/vxe-table/packages/src/grid.ts文件

gridMethods.commitProxy('query')
// insert
// insert_actived
// mark_cancel
// remove
// import
// open_import
// export
// open_export
// reset_custom
// _init
// 重置page 并查询
gridMethods.commitProxy('_init') 
// reload
// 重新载入,可以重置一些参数但并不能重置查询参数
gridMethods.commitProxy('reload') 
// query
// delete
// save

grid在重置之后列表自动查询的时候还是会把原本的数据带过去的问题解决

在被坑的死去活来的时候,发现,grid的查询字段,如果ui不是自带的,这时候就会又有一个问题,那就是点击重置的时候,slots自定义的组件不能重置,后来发现有@form-reset的方法去重置,但是需要自己去写,这一点不是很友好,但是还可以接受

<vxe-grid ref="xGrid"
    class="sl-main-wrapper"
    v-bind="gridOptions"
    @form-reset="gridformReset">
  ...
</vxe-grid>
const gridformReset = ({ data }) => {
  const keys = ['picker', 'stereotypeMaker', 'status']
  keys.forEach((i: any) => {
    data[i] = undefined
  })
}

但是发现了一个问题,我第一次重置的时候,我重置后的值居然带不过去,它还是上一个条件的参数~~,我滴个亲哥,要命啊,找了很多解决方案,首先是代码次序,不行,再次是重新组织查询的参数,发现还是不行,后来在吃饭的时候想起来会不会是因为没有nextTick的原因呢?

果然是!!!!!!!!!!!!!!!!!!!!!!!!!

最后的解决方案是这样的:

以下代码只是我的场景,核心点是return nextTick(() => { return response })

query: ({ page, form }) => {
    return nextTick(async () => {
      const { pageSize: size, currentPage } = page
      const paging = { size, page: currentPage }
      const queryParams: any = Object.assign(paging, form)
      const vxeForm = clone(queryParams, true)
      const picker = vxeForm.picker || []
      if (picker.length > 0) {
        if (form.dateType === 1) {
          vxeForm.tailorCompleteTimeStart = picker[0]
          vxeForm.tailorCompleteTimeEnd = picker[1]
        } else if (form.dateType === 2) {
          vxeForm.stereotypeCompleteTimeStart = picker[0]
          vxeForm.stereotypeCompleteTimeEnd = picker[1]
        }
      }
      delete vxeForm.picker
      delete vxeForm.dateType
      const response = await queryList(vxeForm)
      return response
    })
  }

VxeTable行编辑和Element-UI el-select和el-autocomplete的select事件冲突的问题

今天在开发行编辑时,因为行编辑查询要做远程查询,所以使用了el-autocomplete进行远程查询,但是发现,查询到了数据以后,点击选中时发现无法选中,令我很困惑,最后仔细查看了el-autocomplete这个组件的属性之后,发现popper-append-to-body属性默认是true(我记得好像是false。。。),原来是每次点击select触发了取消行编辑导致点击没有选中,触发了取消行编辑和关闭poper导致,将popper-append-to-body属性改为false即可。

<el-autocomplete
  v-model="row.materialCode"
  value-key="code"
  placeholder=""
  clearable
  :fetch-suggestions="queryWllist"
  @select="(e) => selectWllist(e, row)"
  :popper-append-to-body="false"
></el-autocomplete>

其他问题

暂时还没想到,想到了再更新吧,有兄弟姐妹愿意跟我讨论的可以一起嗷~~

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_38085253/article/details/124865828

智能推荐

常见分布式理论(CAP、BASE)和一致性协议(Gosssip协议、Raft一致性算法)_张维鹏的博客-程序员ITS301

分布式系统只能同时满足CAP中的两种,在设计分布式架构时必须做出取舍,而分区容忍性是基本要求,必须要满足,所以设计分布式系统,就是在一致性和可用性之间取一个平衡。BASE是对CAP中一致性和可用性权衡的结果,核心思想是即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。

视频教程-蜂鸣器-第1季第11部分-单片机/工控_weixin_29373353的博客-程序员ITS301

蜂鸣器-第1季第11部分 互联网课程品牌《朱老师物联网大讲堂》创始人。精通U...

外包!商城分销类微信小程序开发_weixin_40531668的博客-程序员ITS301

请可以做的大佬联系我,微信:jizifengtiannu 电话:13507201937

spring--入门_xxmric的博客-程序员ITS301

一、Spring基本特征1.Spring是一个非常活跃的开源框架;它是一个基于Core来构架多层JavaEE系统的框架,它的主要目地是简化企业开发.   2.Spring的 jar包3.Spring配置文件      默认情况下是applicationContext.xml文件。可以建立很多xml文件,工程中一般都是这样配置的。       xmlns:

广告行业中那些趣事系列26:基于PoseNet算法的人体姿势相似度识别_数据拾光者的博客-程序员ITS301

摘要:本篇从理论到实践分享了基于PoseNet算法的人体姿势相似度识别项目。首先介绍了项目背景,因为部门搞活动需要大家去模仿夸张搞笑的表情和姿势来提升活动的可玩性,所以需要利用CV算法对...

64位win10系统无法安装.Net framework3.5的两种解决方法_小蚂蚁_CrkRes的博客-程序员ITS301

近日有网友反映在windows10_64位系统电脑上安装Net framework3.5,操作时总失败,怎么办呢?小编下面就介绍win10 64位系统无法安装Net framework3.5的两种解决方案吧在Windows10中,当我们安装某些软件的时候会提示“你的电脑上的应用需要使用以下Windows功能:.NET Framework 3.5(包括.NET 2.0和3.0)”。这时就需要

随便推点

【setjmp和longjmp 】 C语言的非局部跳转:setjmp和longjmp(跨函数长跳转)_bdview的博客-程序员ITS301

C标准库&lt;setjmp.h&gt; 非局部跳转&lt;setjmp.h&gt; 头文件&lt;setjmp.h&gt;中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回。 8.1 setjmp #include &lt;setjmp.h&gt; int setjmp(jmp_buf e...

明显调用的表达式前的括号必须具有(指针)函数类型 编译器错误 C2064_weixin_34187862的博客-程序员ITS301

看到“明显调用的表达式前的括号必须具有(指针)函数类型”这句时我才发现我的语文水平有多烂,怎么看都看不懂,折腾了半天才知道是哪里出了问题。举个简单的例子class CTest{ void (CTest::*m_pFun)(); void CallFun() { (this-&gt;*m_pFun)(); //OK,对象指针和函数名一定要用括号括起来,函数名前...

Android 调用系统的设置项_骑行的蜗牛的博客-程序员ITS301

调用方式:Intent mIntent = new Intent();ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.WirelessSettings");mIntent.setComponent(comp);mIntent.setAction("android.i

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component c_hello-java-maker的博客-程序员ITS301

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [C:\Users\Administrator\workspace2.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtp...

python 生成带有alpha 通道的视频_长虹剑的博客-程序员ITS301_python alpah 通道 视频合成

第一次研究的时候弄了一下午,耽误了很多事情,这也是也是在放弃的边缘终于柳暗花明我最终是通过 moviepy 弄出来的,但是 moviepy 一定要装最新版,而且要小心其中的坑。参考资料ffmpeg 带alpha透明层的视频编码从这篇文章中可总结一些关键信息:mp4容器是可以支持透明通道的,编码格式为 png。在我后续的实验中也发现这样子生成的视频能比 mov 这种容器小一些,不过应该会带来视频质量的下降,可能需要传入 -vb 参数增加码率。最终是这个代码帮了我很大的忙,它还让我学到 ffmpeg

推荐文章

热门文章

相关标签