欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue使用el-table實(shí)現(xiàn)表格跨頁(yè)多選

 更新時(shí)間:2023年08月09日 09:34:01   作者:前端手術(shù)刀  
在我們?nèi)粘m?xiàng)目開(kāi)發(fā)中,經(jīng)常會(huì)有表格跨頁(yè)多選的需求,接下來(lái)讓我們用?el-table示例一步步來(lái)實(shí)現(xiàn)這個(gè)需求,文中有詳細(xì)的代碼講解,對(duì)我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

前言

在我們?nèi)粘m?xiàng)目開(kāi)發(fā)中,經(jīng)常會(huì)有 表格跨頁(yè)多選 的需求,接下來(lái)讓我們用 el-table 示例一步步來(lái)實(shí)現(xiàn)這個(gè)需求。

動(dòng)手開(kāi)發(fā)

在線體驗(yàn)

priceless-mcclintock-4cp7x3 - CodeSandbox

常規(guī)版本

本部分只寫(xiě)了一些重點(diǎn)代碼,心急的彥祖可以直接看 性能進(jìn)階版

  1. 首先我們需要初始化一個(gè)選中的數(shù)組 checkedRows
this.checkedRows = [] 
  1. 在觸發(fā)選中的時(shí)候,我們就需要把當(dāng)前行數(shù)據(jù) push checkedRows ,否則就需要剔除對(duì)應(yīng)行
<el-table ref="multipleTable" @select="handleSelectChange">
handleSelectChange (val, row) {
  const checkedIndex = this.checkedRows.findIndex(_row => _row.id === row.id)
  if (checkedIndex > -1) {
    // 選中剔除
    this.checkedRows.splice(checkedIndex, 1)
  } else {
    // 未選中壓入
    this.checkedRows.push(row)
  }
}
  1. 實(shí)現(xiàn)換頁(yè)的時(shí)候的回顯邏輯
this.data.forEach(row=>{
  const checkedIndex = this.checkedRows.findIndex(_row => _row.id === row.id)
  if(checkedIndex>-1) this.$refs.multipleTable.toggleRowSelection(row,true)
})

效果預(yù)覽

讓我們看下此時(shí)的效果

2023-08-08 20.03.52.gif

完整代碼

<template>
  <div>
    <el-table
      ref="multipleTable"
      :data="tableData"
      tooltip-effect="dark"
      style="width: 100%"
      @select="handleSelectChange"
      @select-all="handleSelectAllChange"
    >
      <el-table-column
        type="selection"
        width="55"
      />
      <el-table-column
        label="日期"
        width="120"
        prop="date"
      />
      <el-table-column
        prop="name"
        label="姓名"
        width="120"
      />
    </el-table>
    <el-pagination
      background
      :current-page.sync="currentPage"
      layout="prev, pager, next"
      :total="1000"
      @current-change="currentChange"
    />
  </div>
</template>
<script>
export default {
  data () {
    return {
      currentPage: 1,
      checkedRows: [],
      pageSize: 10,
      totalData: Array.from({ length: 1000 }, (_, index) => {
        return {
          date: '2016-05-03',
          id: index,
          name: '王小虎' + index
        }
      })
    }
  },
  computed: {
    tableData () {
      const { currentPage, totalData, pageSize } = this
      return totalData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
    }
  },
  methods: {
    currentChange (page) {
      this.currentPage = page
      this.tableData.forEach(row => {
        const checkedIndex = this.checkedRows.findIndex(_row => _row.id === row.id)
        if (checkedIndex > -1) this.$refs.multipleTable.toggleRowSelection(row, true)
      })
    },
    handleSelectChange (val, row) {
      const checkedIndex = this.checkedRows.findIndex(_row => _row.id === row.id)
      if (checkedIndex > -1) {
        this.checkedRows.splice(checkedIndex, 1)
      } else {
        this.checkedRows.push(row)
      }
    },
    handleSelectAllChange (val) {
      this.tableData.forEach(row => {
        this.handleSelectChange(null, row)
      })
    }
  }
}
</script>

性能進(jìn)階版

性能缺陷分析

優(yōu)秀的彥祖?zhèn)?應(yīng)該發(fā)現(xiàn)以上代碼的性能缺陷了

1. handleSelectChange 需要執(zhí)行一個(gè) O(n) 復(fù)雜度的循環(huán)

2. currentChange 的回顯邏輯內(nèi)部, 有一個(gè) O(n^2) 復(fù)雜度的循環(huán)

想象一下 如果場(chǎng)景中勾選的行數(shù)達(dá)到了 10000 行, 每頁(yè)顯示 100

那么我們每次點(diǎn)擊換頁(yè) 最壞情況就要執(zhí)行 10000 * 100 次循環(huán),這是件可怕的事...

重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)

其實(shí)我們沒(méi)必要把 checkedRows 設(shè)計(jì)成一個(gè)數(shù)組, 我們可以設(shè)計(jì)成一個(gè) map ,這樣讀取值就只需要 O(1) 復(fù)雜度

1.改造 checkedRows

this.crossPageMap = new Map() 

2.修改選中邏輯( 核心代碼 )

handleSelectChange (val, row) {
  // 實(shí)現(xiàn)了 O(n) 到 O(1) 的提升
  const checked = this.crossPageMap.has(row.id)
  if (checked) {
    this.crossPageMap.delete(row.id)
  } else {
    this.crossPageMap.set(row.id, row)
  }
}

3.修改換頁(yè)回顯邏輯

currentChange (page) {
  this.currentPage = page
  // 實(shí)現(xiàn)了 O(n^2) 到 O(n) 的提升
  this.tableData.forEach(row => {
    const checked = this.crossPageMap.has(row.id)
    if (checked) this.$refs.multipleTable.toggleRowSelection(row, true)
  })
}

完整代碼

<template>
  <div>
    <el-table
      ref="multipleTable"
      :data="tableData"
      tooltip-effect="dark"
      style="width: 100%;height:500px"
      @select="handleSelectChange"
      @select-all="handleSelectAllChange"
    >
      <el-table-column
        type="selection"
        width="55"
      />
      <el-table-column
        label="日期"
        width="120"
        prop="date"
      />
      <el-table-column
        prop="name"
        label="姓名"
        width="120"
      />
    </el-table>
    <el-pagination
      background
      :current-page.sync="currentPage"
      layout="prev, pager, next"
      :total="1000"
      @current-change="currentChange"
    />
  </div>
</template>
<script>
export default {
  data () {
    return {
      currentPage: 1,
      crossPageMap: new Map(),
      pageSize: 10,
      totalData: Array.from({ length: 1000 }, (_, index) => {
        return {
          date: '2016-05-03',
          id: index,
          name: '王小虎' + index
        }
      })
    }
  },
  computed: {
    tableData () {
      const { currentPage, totalData, pageSize } = this
      return totalData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
    }
  },
  methods: {
    currentChange (page) {
      this.currentPage = page
      this.tableData.forEach(row => {
        const checked = this.crossPageMap.has(row.id)
        if (checked) this.$refs.multipleTable.toggleRowSelection(row, true)
      })
    },
    handleSelectChange (val, row) {
      const checked = this.crossPageMap.has(row.id)
      if (checked) {
        this.crossPageMap.delete(row.id)
      } else {
        this.crossPageMap.set(row.id, row)
      }
    },
    handleSelectAllChange (val) {
      this.tableData.forEach(row => {
        this.handleSelectChange(null, row)
      })
    }
  }
}
</script>

抽象業(yè)務(wù)邏輯

以上就是完整的業(yè)務(wù)代碼部分,但是為了復(fù)用性。

我們考慮可以把其中的邏輯抽象成一個(gè) CrossPage

設(shè)計(jì) CrossPage 類

接收以下參數(shù)

`data` - 行數(shù)據(jù)
`key` - 行數(shù)據(jù)唯一值
`max` - 最大選中行數(shù)
`toggleRowSelection` - 切換行數(shù)據(jù)選中/取消選中的方法

提供以下方法

`onRowSelectChange` - 外部點(diǎn)行數(shù)據(jù)點(diǎn)擊的時(shí)候調(diào)用此方法
`onDataChange` - 外部數(shù)據(jù)變化的時(shí)候調(diào)用此方法
`clear` - 清空所有選中行

構(gòu)造器大致代碼 如下

constructor (options={}) {
    this.crossPageMap = new Map()
    this.key = options.key || 'id'
    this.data = options.data || []
    this.max = options.max || Number.MAX_SAFE_INTEGER
    this.toggleRowSelection = options.toggleRowSelection
    if(typeof this.toggleRowSelection !== 'function') throw new Error('toggleRowSelection is not function')
}

設(shè)置私有crossPageMap

彥祖?zhèn)?問(wèn)題來(lái)了,我們把 crossPageMap 掛載到實(shí)例上,那么外部就可以直接訪問(wèn)修改這個(gè)變量。

這可能導(dǎo)致我們內(nèi)部的數(shù)據(jù)邏輯錯(cuò)亂,所以必須禁止外部訪問(wèn)。

我們可以使用 # 修飾符來(lái)實(shí)現(xiàn)私有屬性,具體參考

類私有域 - JavaScript | MDN (mozilla.org)

完整代碼

  • CrossPage.js
/**
 * @description 跨頁(yè)選擇
 * @param {Object} options
 * @param {String} options.key 行數(shù)據(jù)唯一標(biāo)識(shí)
 * @param {Array} options.data 行數(shù)據(jù)
 * @param {Number} options.max 最大勾選行數(shù)
 * @param {Function} options.toggleRowSelection 設(shè)置行數(shù)據(jù)選中/取消選中的方法,必傳
 */
export const CrossPage = class {
  #crossPageMap = new Map();
  constructor (options={}) {
    this.key = options.key || 'id'
    this.data = options.data || []
    this.max = options.max || Number.MAX_SAFE_INTEGER
    this.toggleRowSelection = options.toggleRowSelection
    if(typeof this.toggleRowSelection !== 'function') throw new Error('toggleRowSelection is not function')
  }
  get keys(){
    return Array.from(this.#crossPageMap.keys())
  }
  get values(){
    return Array.from(this.#crossPageMap.values())
  }
  get size(){
    return this.#crossPageMap.size
  }
  clear(){
    this.#crossPageMap.clear()
    this.updateViews()
  }
  onRowSelectChange (row) {
    if(typeof row !== 'object') return console.error('row is not object')
    const {key,toggleRowSelection} = this
    const checked = this.#crossPageMap.has(row[key])
    if(checked) this.#crossPageMap.delete(row[key])
    else {
      this.#crossPageMap.set(row[key],row)
      if(this.size>this.max){
        this.#crossPageMap.delete(row[key])
        toggleRowSelection(row,false)
      }
    }
  }
  onDataChange(list){
    this.data = list
    this.updateViews()
  }
  updateViews(){
    const {data,toggleRowSelection,key} = this
    data.forEach(row=>{
      toggleRowSelection(row,this.#crossPageMap.has(row[key]))
    })
  }
}
  • crossPage.vue
<template>
  <div>
    <el-table
      ref="multipleTable"
      :data="tableData"
      tooltip-effect="dark"
      style="width: 100%"
      @select="handleSelectChange"
      @select-all="handleSelectAllChange"
    >
      <el-table-column
        type="selection"
        width="55"
      />
      <el-table-column
        label="日期"
        width="120"
        prop="date"
      />
      <el-table-column
        prop="name"
        label="姓名"
        width="120"
      />
    </el-table>
    <el-button @click="clear">
      清空
    </el-button>
    <el-button @click="keys">
      獲取 keys
    </el-button>
    <el-button @click="values">
      獲取 values
    </el-button>
    <el-pagination
      background
      :current-page.sync="currentPage"
      layout="prev, pager, next"
      :total="1000"
      @current-change="currentChange"
    />
  </div>
</template>
<script>
import { CrossPage } from './CrossPage'
export default {
  data () {
    return {
      currentPage: 1,
      pageSize: 10,
      totalData: Array.from({ length: 1000 }, (_, index) => {
        return {
          date: '2016-05-03',
          id: index,
          name: '王小虎' + index
        }
      }),
      multipleSelection: []
    }
  },
  computed: {
    tableData () {
      const { currentPage, totalData, pageSize } = this
      return totalData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
    }
  },
  mounted () {
    this.crossPageIns = new CrossPage({
      key: 'id',
      max: 2,
      data: this.tableData,
      toggleRowSelection: this.$refs.multipleTable.toggleRowSelection
    })
  },
  methods: {
    clear () {
      this.crossPageIns.clear()
    },
    keys () {
      console.log('keys:', this.crossPageIns.keys)
    },
    values () {
      console.log('values:', this.crossPageIns.values)
    },
    currentChange (page) {
      this.currentPage = page
      // 調(diào)用實(shí)例 onDataChange 方法
      this.crossPageIns.onDataChange(this.tableData)
    },
    handleSelectChange (val, row) {
      // 調(diào)用實(shí)例 onRowSelectChange 方法
      this.crossPageIns.onRowSelectChange(row)
    },
    handleSelectAllChange (val) {
      this.tableData.forEach(row => {
        this.crossPageIns.onRowSelectChange(row)
      })
    }
  }
}
</script>

寫(xiě)在最后

未來(lái)想做的還有很多

  • 利用 requestIdleCallback 提升單頁(yè)大量數(shù)據(jù)的 toggleRowSelection 渲染效率
  • 提供默認(rèn)選中項(xiàng)的配置
  • ...

以上就是Vue使用el-table實(shí)現(xiàn)表格跨頁(yè)多選的詳細(xì)內(nèi)容,更多關(guān)于Vue el-table表格跨頁(yè)多選的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue中created與mounted的區(qū)別淺析

    Vue中created與mounted的區(qū)別淺析

    在使用vue框架的過(guò)程中,我們經(jīng)常需要給一些數(shù)據(jù)做一些初始化處理,這時(shí)候我們常用的就是在created與mounted選項(xiàng)中作出處理,這篇文章主要給大家介紹了關(guān)于Vue中created與mounted區(qū)別的相關(guān)資料,其中部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的,需要的朋友可以參考下
    2022-06-06
  • Vue關(guān)閉當(dāng)前彈窗頁(yè)面的兩種方式

    Vue關(guān)閉當(dāng)前彈窗頁(yè)面的兩種方式

    這篇文章主要給大家介紹了關(guān)于Vue關(guān)閉當(dāng)前彈窗頁(yè)面的兩種方式,這是最近項(xiàng)目中遇到的一個(gè)需求,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • vue實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)增刪改查的示例代碼

    vue實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)增刪改查的示例代碼

    其實(shí)很多公司都會(huì)有類似于用戶權(quán)限樹(shù)的增刪改查功能,本文主要介紹了vue實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)增刪改查,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 詳解如何在Vue中快速實(shí)現(xiàn)數(shù)據(jù)可視化大屏展示

    詳解如何在Vue中快速實(shí)現(xiàn)數(shù)據(jù)可視化大屏展示

    在現(xiàn)代數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用程序中,數(shù)據(jù)可視化大屏已經(jīng)成為了非常重要的一環(huán),通過(guò)對(duì)海量數(shù)據(jù)進(jìn)行可視化展示,可以幫助用戶更好地理解和分析數(shù)據(jù),從而做出更加明智的決策,在Vue中進(jìn)行數(shù)據(jù)可視化大屏展示也變得越來(lái)越流行,本文將介紹如何在Vue中快速實(shí)現(xiàn)數(shù)據(jù)可視化大屏展示
    2023-10-10
  • 基于Vue.js實(shí)現(xiàn)數(shù)字拼圖游戲

    基于Vue.js實(shí)現(xiàn)數(shù)字拼圖游戲

    為了進(jìn)一步讓大家了解Vue.js的神奇魅力,了解Vue.js的一種以數(shù)據(jù)為驅(qū)動(dòng)的理念,本文主要利用Vue實(shí)現(xiàn)了一個(gè)數(shù)字拼圖游戲,其原理并不是很復(fù)雜,下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)。
    2016-08-08
  • 詳解Vue computed計(jì)算屬性是什么

    詳解Vue computed計(jì)算屬性是什么

    在vue中,有時(shí)候你需要對(duì)data中的數(shù)據(jù)進(jìn)行處理,或者對(duì)抓取的數(shù)據(jù)進(jìn)行處理之后再掛載呈現(xiàn)到標(biāo)簽中,這時(shí)候你就需要計(jì)算屬性了,當(dāng)然看到這里你可能還是不了解那下面我舉幾個(gè)實(shí)例并附代碼解釋
    2023-03-03
  • vue3.0公共組件自動(dòng)導(dǎo)入的方法實(shí)例

    vue3.0公共組件自動(dòng)導(dǎo)入的方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于vue3.0公共組件自動(dòng)導(dǎo)入的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • vue 動(dòng)態(tài)表單開(kāi)發(fā)方法案例詳解

    vue 動(dòng)態(tài)表單開(kāi)發(fā)方法案例詳解

    這篇文章主要介紹了vue 動(dòng)態(tài)表單開(kāi)發(fā)方法,結(jié)合具體案例形式詳細(xì)分析了vue.js動(dòng)態(tài)表單相關(guān)原理、開(kāi)發(fā)步驟與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-12-12
  • vue使用原生js實(shí)現(xiàn)滾動(dòng)頁(yè)面跟蹤導(dǎo)航高亮的示例代碼

    vue使用原生js實(shí)現(xiàn)滾動(dòng)頁(yè)面跟蹤導(dǎo)航高亮的示例代碼

    這篇文章主要介紹了vue使用原生js實(shí)現(xiàn)滾動(dòng)頁(yè)面跟蹤導(dǎo)航高亮的示例代碼,滾動(dòng)頁(yè)面指定區(qū)域?qū)Ш礁吡?。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • vue配置electron使用electron-builder進(jìn)行打包的操作方法

    vue配置electron使用electron-builder進(jìn)行打包的操作方法

    這篇文章主要介紹了vue配置electron使用electron-builder進(jìn)行打包的操作方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-08-08

最新評(píng)論