More articles

preface

To continue the combined API, today we share useTable. In fact, we have shared useTable before, but there is no business verification. After a period of business practice, here we share a version more complete than before

introduce

UseTable is the encapsulation of the basic logic of the list class. UI representation may be in the form of table, list, etc. Extensions such as useTableEdit, useTableColumn, etc. are completed on the basis of useTable. In addition, lists and paging information follow each other. So useTable contains paging information

Based on using

<template> <div> <Table :dataSource="dataSource" :columns="columns" :loading="loading" /> <Pagination :pagination="pagination" /> </div> </template> <script> import Table from '@/components/table' import Pagination from '@/components/qjd/pagination' import useTable from '@/hooks/useTable' import { columns } from './config' export default { components: {Table, Pagination}, setup() {Table dataSource: Pagination, request: Const {dataSource, pagination, loading} = useTable({request}) return {dataSource, pagination, loading, columns } } } </script>Copy the code

Initialization is not called

For some scenarios that do not need to trigger an interface call during initialization, set isInit to false. The default is true


const { dataSource } = useTable({ request, isInit: false })
Copy the code

The default parameters

Default initialization parameters can be set using defaultParams. Default is {}.


const { dataSource } = useTable({ request, defaultParams: { id: 1}})Copy the code

Is there pagination

IsPage defaults to true and is set to false if pagination is not required


const { dataSource } = useTable({ request, isPage: false })
Copy the code

The interface returned invalid data. Procedure

According to the convention, usually the data returned by the back end conforms to the processing of useTable, but does not exclude the case that does not comply, the data can be processed through callback

The returned data must be in the {totalCount, dataSource} format


const { dataSource } = useTable({
  request,
  callback: ({ code, data }) = > {
    return code === '0' ? { totalCount: data? .total ||0.dataSource: data? .data || [] } : {} } })Copy the code

Dynamic header

When the header is dynamic, the incoming parameter needs to pass a column and isActiveColumn, and the outgoing parameter needs to pass another reactive column and the method setColumns to update the reactive data. IsActiveColumn tells useTable to mix useTableColumn logic


const {
  columns,
  dataSource,
  setColumns
} = useTable({
  request,
  isActiveColumn: true.columns: defaultColumns
})
// Set the table header
const changeColumns = cols = > setColumns(cols)
Copy the code

Editable table

When a paginated list is edited without a real-time request from the back end to store data, the edited data will be lost when switching paginated request data, and editable table is the solution to this problem. Like dynamic table headers, editable tables do not belong to the basic table function. You need to pull a separate use function to complete the table and mix it with useTable through input methods

Setting Edit to true tells useTable to blend in the useTableEdit logic


const { dataSource, setEditChange } = useTable({ request, edit: true })
// If the table has an input and the event that listens for changes in the input data is onChange, then the edit data can be stored when the onChange event is triggered
// setEditChange: Stores the current edited data. After storing the data, the page will carry the previously edited data when switching
const onChange = () = > setEditChange(dataSource)
Copy the code

Pops up the table

If you want to use a custom checkbox, you can use a new use function to retrieve the original checkbox logic (annotated in the useTableCheckBox). Multi-select tables are also not part of the basic table function. To cope with paging switching, Element provides this function. Reserve-selection is optional

Set checkbox to true to enable multiple selection


const { dataSource, selectionChange  } = useTable({ request, checkbox: true })
// Set selectionHandle to the selection-change event of element-table
const selectionHandle = vals= > selectionChange(vals)
Copy the code

The source code

All the logic that does not belong to the basic table function is implemented by a separate use function. In the introduction of useTable, only the logic related to the basic table is released


import { reactive, toRefs, ref, onUnmounted } from '@vue/composition-api'
import { deepCopy } from '@/utils/qjd'
import useAsync from './useAsync'
// Dynamic table header - logic
import useTableColumn from './useTableColumn'
/ / the checkbox - logic
import useTableCheckBox from './useTableCheckBox'
// edit table- logic
import useTableEdit from './useTableEdit'

/** Applies to general table & page, with components/ QJD /table and Pagination. Currently, the component is only used in the development of the scene, what is missing is added, according to the actual scene extension useTbale *@param Request Interface or Array<any> *@param DefaultParams is the default entry parameter *@param IsInit whether to initialize the call *@param IsPage is paged *@param Checkbox Specifies whether to enable multiple select mode and mix multiple select logic *@param Edit Whether to enable edit mode and blend in edit logic *@function Callback Provides a fault tolerance mechanism * if the interface does not return sufficient data@param Columns need to be entered if the columns are dynamic headers. The useTable header is used later. If the columns are static, * is not required@param IsActiveColumn Whether to enable dynamic form mode */

const defaultCallBack = (data = {}) = > {
  const { totalCount = 0, pagedRecords = [] } = data || {}
  return {
    totalCount,
    dataSource: pagedRecords
  }
}

function useTable({
  request,
  defaultParams = {},
  isInit = true,
  isPage = true,
  checkbox = false,
  edit = false,
  callback = defaultCallBack,
  columns = [],
  isActiveColumn = false
}) {
  const c = defaultParams && defaultParams.current ? defaultParams.current : 1
  const p = defaultParams && defaultParams.pageSize ? defaultParams.pageSize : 10

  const current = ref(c)
  const pageSize = ref(p)
  // Store the anti-shake function
  const timer = ref(null)

  const state = reactive({
    params: isPage ? Object.assign({ page: current, pageSize: pageSize }, defaultParams) : defaultParams,
    searchInfo: {},
    dataSource: [].pagination: {
      current: current,
      pageSize: pageSize,
      total: 0.onChange: (page, pageSize) = > pageChange(page, pageSize),
      onShowSizeChange: (current, size) = > showSizeChange(current, size)
    }
  })

  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- whether to insert dynamic header logic start -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
  // Insert the useTableColumn logic here
  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- whether to insert dynamic header logic end -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- whether to insert the checkbox multi-select logic start -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
  // Insert useTableCheckBox logic here
  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- whether to insert the checkbox multi-select logic end -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- whether to insert editable table logic start -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
  // Insert useTableEdit logic here
  / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- whether to insert editable table logical end -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

  // Successful callback
  const successCallBack = ({ code, data }) = > {
    if (code === '0') {
      // Callback processes data
      const result = callback ? callback(data) : data
      const { totalCount = 0, dataSource = [] } = result || {}
      state.pagination.total = totalCount || (dataSource ? dataSource.length : 0)
      state.dataSource = dataSource
      // Echo data in edit mode
      edit && setEditDataSource(state.dataSource, current.value)
    }
  }
  / / interface
  const { doResult, loading } = useAsync({
    request,
    init: false.params: {},
    successCallBack
  })
  // API request or JSON
  const _request = (params = {}) = > {
    if (Object.prototype.toString.call(request) === '[object Array]') { // Use the JSON data passed in at definition
      state.dataSource = request
      state.pagination.total = request.length
    } else if (Object.prototype.toString.call(request) === '[object Function]') { // Use the API request passed in when the definition is useddoResult({ ... state.params, ... params }) } }/ / query
  const searchHandle = (searchInfo = {}) = > {
    // Copy data to prevent upper-layer data from being affected
    searchInfo = deepCopy(searchInfo)
    current.value = c
    pageSize.value = p
    state.pagination.current = searchInfo.page ? searchInfo.page : c
    state.pagination.pageSize = searchInfo.pageSize ? searchInfo.pageSize : p
    state.searchInfo = searchInfo
    _request(searchInfo)
  }
  // If the current page is not the first page and the data after the switch is only one page, pageChange will be triggered after showSizeChange is triggered
  const _deferRequest = () = > {
    timer.value && clearTimeout(timer.value)
    timer.value = setTimeout(() = > {
      _request(state.searchInfo)
    }, 0)}// Toggle pages
  const pageChange = (page, pageSize) = > {
    current.value = page
    state.searchInfo.page = page
    _deferRequest()
  }
  // Switch the number of entries
  const showSizeChange = (current, size) = > {
    pageSize.value = current
    state.searchInfo.pageSize = current
    _deferRequest()
  }
  / / reset
  const resetHandle = () = > {
    state.searchInfo = {}
    current.value = c
    pageSize.value = p
    _request({})
  }
  // Clear the data
  const clearHandle = () = > {
    state.dataSource = []
    current.value = c
    pageSize.value = p
  }
  // Initialize the data
  isInit && _request(state.params)
  // Clear the timer
  onUnmounted(() = > {
    if (timer.value) {
      clearTimeout(timer.value)
      timer.value = null}})return {
    ...toRefs(state),
    loading,
    searchHandle,
    resetHandle,
    clearHandle,
    // checkbox Select multiple states & interfaces. checkBoxParams,// Edit table status & interface. editParams,// Dynamic table header related state & interface. activeColParams, } }export default useTable
Copy the code

The ginseng

parameter instructions type An optional value The default value
request Interface request Promise
defaultParams The interface requests the default input parameter Object {}
isInit Whether to initiate an interface request Boolean true
isPage Is there pagination Boolean true
callback The interface requests a data processing callback Function(data)
columns To dynamic the header, you need to pass columns, referring to element Arrary []
isActiveColumn Whether to enable the dynamic table header Boolean false
checkbox Whether to enable multiple selection Boolean false
edit Whether to enable table editable Boolean false

The ginseng

parameter instructions type An optional value The default value
dataSource Interface request data Arrary []
pagination The paging information Object
searchInfo Query conditions Object {}
loading Loading status Boolean false
searchHandle Actively triggers the interface to invoke a method Function(params)
resetHandle Reset (Reset query criteria &dataSource) Function
clearHandle Clear data & reset paging information Function

Pagination

key instructions The default value
current The current number of pages 1
pageSize The current article number 10
total The total number of article 0
onChange Page number change event Function(page, pageSize)
onShowSizeChange Number change event Function(current, size)

The outgoing parameter added after isActiveColumn is enabled

parameter instructions type An optional value The default value
columns The columns configuration Arrary []
setColumns Set up the columns Function(data)

Enable the checkbox output parameter

parameter instructions type An optional value The default value
currentSelects Currently selected data Arrary []
setCurrentSelects Set the currentSelects Function(data)
selectionChange If currentSelects is set, checkBox is not enabled Function(data)

Enable the output parameter added after Edit

SetEditChange is the key to the data echo. This method is triggered to set the editDatas after the data is edited to ensure that the data can be displayed properly during the page switch

parameter instructions type An optional value The default value
editDatas Edit the data Object {}
clearEdits Clearing edit data Function
setEditChange Set edit data Function(data: any[])

conclusion

Table function is quite complex, there will be part of the logic away, mainly depends on the business encountered what kind of requirements, here to complete the packaging of this part of the logic in direct use will be good, the next article to share useForm