SoFunction
Updated on 2025-03-10

Various pits and pit avoidance guides in Vxe-Table development

background:

Since the company wanted to develop erp, it used element-plus as the basic UI framework. However, looking back on the past, the various performances of element-ui tables were heartbreaking. So after discussing with the leader, I decided to use Vxe-Table as the table plug-in. Although element-plus is also vigorously optimizing the table, the availability is not high at present. A virtual scroll has just been released, but it really looks a bit impatient. . .

Various problems encountered in the development stage

The problem of global size

It's a bit silly. I want to make global size modifications for element-plus, which means that my table also needs to make global size modifications. Fortunately, it has its own global size configuration and the configuration method is also very simple. It can be set in the setup method, and it can be done in conjunction with vuex, local storage (including cookies), and there are also some pretty things that can be done. Unfortunately, the size and element-plus size rules are very different. Although this problem can be avoided by modifying and changing the quantity, the cost is really a bit high. Moreover, element-plus is large, default, and small, but Vxe-Table is medium, small, and mini. It also needs to be judged. It is complicated and a little disgusting. The code is attached below.

import 'xe-utils'
import VXETable from 'vxe-table'
import 'vxe-table/lib/'
//Introduce font-awesomeimport 'font-awesome/css/'
import { localAppSizeKey } from '@/store/modules/settings/index'
 
({
  size: formatSize((localAppSizeKey) || 'default') as any
})
 
export default function (app: any) {
  (VXETable)
  // Mount internal objects to the vue instance, for example:  // .$XModal = 
  // .$XPrint = 
  // .$XSaveFile = 
  // .$XReadFile = 
}
 
/**
  * parse the global size of element-plus
  * @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 exists in localStorage. Set it once and update the value once. I am very simple and crude here. Set the size of element-plus globally and parse it through the format method, save it to local storage, and then refresh the page. Ah hahahaha, I just don’t know what to do. If someone knows, please try to solve this problem.

Button problem

To be honest, I can understand the author's design pattern very well, and I admire the author's code skills very much. After all, I am just a user, but, if you develop a set of buttons yourself, can you use snacks? The text in the button cannot be vertically centered. What's the era of this? Attached is the code for me to deal with the vertical centering of the buttons

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

Simple and crude, flex, solve the problem

Issues with merging cells

The cell merger was followed by the case provided by the official website. The spanMethod method was used for the first time. At that time, the amount of data was small and virtual scrolling was not enabled. Later, the amount of data was large. The test rolled and screamed. I knew something was wrong after a numbness on my scalp. As a result, I saw that it was written on the official website that virtual scrolling is not supported. Alas~~ Isn’t this form just for virtual scrolling? I found a solution and later decided to use [mergeCells] to solve this problem. The solution is to merge fixed columns according to the needs, and then query the most recent same data in the data (the backend has been sorted in order), generate the data to be merged, and then assign it to the gridOptions object. The specific implementation is as follows:

proxyConfig: {
    seq: true,
    sort: true,
    filter: true,
    form: true,
    props: {
      result: '',
      total: ''
    },
    ajax: {
      query: async ({ page, form }) => {
        const { pageSize: size, currentPage } = page
        const paging = { size, page: currentPage }
        const queryParams: any = ({ isOdm: 1 }, paging, form)
        const response = await queryList(queryParams)
        // Merge cell options        let mergeCells: any[] = []
        mergeCells = generateMergeCells(
          ,
          'spuName',
          [2, 3, 4, 5, 6, 7, 8]
        )
         = mergeCells
        return response
      }
    }
  },

At this time, the first page can be paging, but after jumping to the page, I found a problem. Is the paging of the second page actually messed up? All behind are in chaos! ! For this reason, Google and Baidu checked it, but there was still no solution. Later, I had a sudden idea. Will it be better to reload each time I paginate it, and the result is really enough. In fact, I just added a line of code to the previous code: ()

proxyConfig: {
    seq: true,
    sort: true,
    filter: true,
    form: true,
    props: {
      result: '',
      total: ''
    },
    ajax: {
      query: async ({ page, form }) => {
        const { pageSize: size, currentPage } = page
        const paging = { size, page: currentPage }
        const queryParams: any = ({ isOdm: 1 }, paging, form)
        const response = await queryList(queryParams)
        // Merge cell options        let mergeCells: any[] = []
        mergeCells = generateMergeCells(
          ,
          'spuName',
          [2, 3, 4, 5, 6, 7, 8]
        )
         = mergeCells
        ()
        return response
      }
    }
  },

Wuhu~~, solve it! Attach the code to dynamically generate mergeCells

// Generate merged cell dataexport const generateMergeCells = (
  data: any[],
  key: string,
  cols: number[]
) => {
  if ( === 0) return []
  let pointer: number = 0
  let total: number = 0
  let curKeyValue: any = data[0][key]
  const result = ((acc: any[], cur: any, index: number) => {
    const val = cur[key]
    let mergeData: any = []
    if (val !== curKeyValue) {
      // Generate merged data      if (total > 1) {
        mergeData = generateCells(cols, pointer, total)
      }
      curKeyValue = val
      pointer = index // Pointer index assignment      total = 1
    } else {
      total += 1
      if (index ===  - 1) {
        mergeData = generateCells(cols, pointer, total)
      }
    }
    (...mergeData)
    return acc
  }, [])
  return result
}
 
export const generateCells = (
  cols: number[],
  rowIndex: number,
  rowspan: number
) => {
  return ((col: number) => {
    return {
      row: rowIndex,
      col,
      rowspan,
      colspan: 1
    }
  })
}

Reload and load issues

I really don't understand why every time the reload and load pass parameters, but the reset and query button method is not thrown for call.

But it can also be solved. The author has thrown many methods, but the explanation document does not..., please refer to it for details.node_modules/vxe-table/packages/src/document

('query')
// insert
// insert_actived
// mark_cancel
// remove
// import
// open_import
// export
// open_export
// reset_custom
// _init
// Reset page and query('_init') 
// reload
// Reload, you can reset some parameters but cannot reset the query parameters('reload') 
// query
// delete
// save

When the grid is automatically queryed after reset, it will still solve the problem of bringing the original data over.

When I was trapped, I found that if the ui of grid query field is not built into it, there will be another problem, that is, when clicking to reset, the custom slots component cannot be reset. Later, I found that there is a @form-reset method to reset, but I need to write it myself. This is not very friendly, but it is acceptable

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

But I found a problem. When I reset the first time, I couldn't bring the value after resetting it. It was still a parameter of the previous condition~~, I'm so deadly. I found a lot of solutions. First of all, the code order is not possible. Again, the parameters of the query are reorganized, but I found that it still is not possible. Later, when I was having a meal, I remembered that it was because there was no nextTick?

Sure enough! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

The final solution is this:

The following code is just my scenario, the core point is return nextTick(() => { return response })

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

Summarize

This is the article about various pitfalls and pit avoidance guides in Vxe-Table development. For more related contents of Vxe-Table pit avoidance guides, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!