Cette fois, je vais vous présenter comment utiliser Element-UI Table pour implémenter la fonction glisser-déposer. Quelles sont les précautions à prendre pour utiliser Element-UI Table pour implémenter la fonction glisser-déposer ? un regard.
Le composant Table d'Element-UI est très puissant, mais nos besoins sont encore plus puissants...
Un rendu simple et brut :
1. Basés sur les données
Les effets de glisser traditionnels sont tous basés sur la modification via les événements mousedown, mousemove, mouseup Supprimez le nœud dom.
Mais Vue est un framework frontal basé sur les données. Vous devriez essayer d'éviter d'utiliser le dom pendant le développement
Et le composant Table d'Element-UI est très rigoureusement encapsulé, il l'est donc. facile d'utiliser directement le dom. Générer des bugs imprévisibles
Mon idée principale est donc : Rendre l'en-tête du tableau (colonne) à travers un tableau, puis modifier l'ordre du tableau, modifiant ainsi le tri des colonnes de la liste
partie modèle :
<p class="w-table" :class="{'w-table_moving': dragState.dragging}"> <el-table :data="data" :border="option.border" :height="option.height" :max-height="option.maxHeight" :style="{ width: parseInt(option.width)+'px' }" :header-cell-class-name="headerCellClassName" > <slot name="fixed"></slot> <el-table-column v-for="(col, index) in tableHeader" :key="index" :prop="col.prop" :label="col.label" :width="col.width" :min-width="col.minWidth" :type="col.type" :header-align="col.headerAlign" :column-key="index.toString()" :render-header="renderHeader" > </el-table-column> </el-table> </p>
Les données ci-dessus sont la collecte de données de la liste, l'option est l'élément de configuration du composant Table et le header est la collection de données d'en-tête de table, qui est transmise depuis le composant parent
props: { data: { default: function () { return [] }, type: Array }, header: { default: function () { return [] }, type: Array }, option: { default: function () { return {} }, type: Object } }
Les éléments de configuration peuvent être supprimés selon l'API d'Element-UI
Mais plusieurs paramètres sont requis à l'intérieur du composant :
1. header-cell -class-name
lie une fonction pour ajouter dynamiquement une classe à la cellule d'en-tête pour obtenir l'effet de ligne pointillée lors du glissement.
2. column-key
est lié à l'index du tableau d'en-tête, utilisé pour déterminer l'indice de l'élément d'en-tête qui doit être modifié
3. render-header
La fonction de rendu d'en-tête est utilisée pour ajouter des méthodes personnalisées pour surveiller le déplacement de la souris et d'autres événements associés
2. status
Plusieurs paramètres clés doivent être enregistrés lors du processus de glisser :
data () { return { tableHeader: this.header, dragState: { start: -1, // 起始元素的 index end: -1, // 结束元素的 index move: -1, // 移动鼠标时所覆盖的元素 index dragging: false, // 是否正在拖动 direction: undefined // 拖动方向 } } }
De plus, l'élément parent passe dans un header data header, mais ces données seront modifiées une fois le glissement terminé
Il n'est pas recommandé de modifier directement les données de l'élément parent dans le composant enfant, donc un tableHeader est initialisé ici pour héberger l'en-tête des données d'en-tête
Mais dans l'ordre pour permettre la modification de l'en-tête, le tableHeader peut également répondre à la modification. Vous devez ajouter une montre de moniteur
watch: { header (val, oldVal) { this.tableHeader = val } }
3. Personnaliser l'en-tête du tableau
Le composant Table d'Element-UI afin d'implémenter la fonction [faites glisser la bordure pour modifier la largeur de la colonne] n'expose pas les trois événements mousemove, mouseup et mousedown , vous devez donc personnaliser l'en-tête et manuellement ajoutez la fonction de traitement des événements de la souris, qui nécessite l'utilisation de la méthoderenderHeader()
renderHeader (createElement, {column}) { return createElement( 'p', { 'class': ['thead-cell'], on: { mousedown: ($event) => { this.handleMouseDown($event, column) }, mouseup: ($event) => { this.handleMouseUp($event, column) }, mousemove: ($event) => { this.handleMouseMove($event, column) } } }, [ // 添加 <a> 用于显示表头 label createElement('a', column.label), // 添加一个空标签用于显示拖动动画 createElement('span', { 'class': ['virtual'] }) ]) },
column.columnKey pour obtenir l'index d'indice de l'élément d'en-tête correspondant
l'étiquette vide est utilisée. Afficher l'animation lors du glissement (ligne pointillée)4. Traitement des événements
Quand la souris est enfoncée, enregistrez la colonne de départ. Lorsque la souris est levée, la colonne de fin est enregistrée. La direction de la traînée est calculée en fonction de la différence entre les deux. Ensuite, les données d'en-tête sont réorganisées en fonction des positions de la colonne de début et de la colonne de fin, réalisant ainsi le glissement de colonne La fonction de traitement du processus de glissement est la suivante :// 按下鼠标开始拖动 handleMouseDown (e, column) { this.dragState.dragging = true this.dragState.start = parseInt(column.columnKey) // 给拖动时的虚拟容器添加宽高 let table = document.getElementsByClassName('w-table')[0] let virtual = document.getElementsByClassName('virtual') for (let item of virtual) { item.style.height = table.clientHeight - 1 + 'px' item.style.width = item.parentElement.parentElement.clientWidth + 'px' } }, // 鼠标放开结束拖动 handleMouseUp (e, column) { this.dragState.end = parseInt(column.columnKey) // 记录起始列 this.dragColumn(this.dragState) // 初始化拖动状态 this.dragState = { start: -1, end: -1, move: -1, dragging: false, direction: undefined } }, // 拖动中 handleMouseMove (e, column) { if (this.dragState.dragging) { let index = parseInt(column.columnKey) // 记录起始列 if (index - this.dragState.start !== 0) { this.dragState.direction = index - this.dragState.start < 0 ? 'left' : 'right' // 判断拖动方向 this.dragState.move = parseInt(column.columnKey) } else { this.dragState.direction = undefined } } else { return false } }, // 拖动易位 dragColumn ({start, end, direction}) { let tempData = [] let left = direction === 'left' let min = left ? end : start - 1 let max = left ? start + 1 : end for (let i = 0; i < this.tableHeader.length; i++) { if (i === end) { tempData.push(this.tableHeader[start]) } else if (i > min && i < max) { tempData.push(this.tableHeader[ left ? i - 1 : i + 1 ]) } else { tempData.push(this.tableHeader[i]) } } this.tableHeader = tempData },
5. Effet de ligne pointillée
Pendant le processus de glissement, utilisez l'événement mousemove pour modifier l'état de l'en-tête de la colonne actuelle puis utilisezheaderCellClassName Modifier dynamiquement sa classe
headerCellClassName ({column, columnIndex}) { return (columnIndex - 1 === this.dragState.move ? `darg_active_${this.dragState.direction}` : '') }
<style lang="scss"> .w-table { .el-table th { padding: 0; .virtual{ position: fixed; display: block; width: 0; height: 0; margin-left: -10px; z-index: 99; background: none; border: none; } &.darg_active_left { .virtual { border-left: 2px dotted #666; } } &.darg_active_right { .virtual { border-right: 2px dotted #666; } } } .thead-cell { padding: 0; display: inline-flex; flex-direction: column; align-items: left; cursor: pointer; overflow: initial; &:before { content: ""; position: absolute; top: 0; left: 0; bottom: 0; right: 0; } } &.w-table_moving { .el-table th .thead-cell{ cursor: move !important; } .el-table__fixed { cursor: not-allowed; } } }
6. Parent appel de composant
<template> <p> <wTable :data="tableData" :header="tableHeader" :option="tableOption"> <el-table-column slot="fixed" fixed prop="date" label="日期" width="150"> </el-table-column> </wTable> </p> </template> <script> import wTable from '@/components/w-table.vue' export default { name: 'Table', data () { return { tableOption: { border: true, maxHeight: 500 }, tableHeader: [{ prop: 'name', label: '姓名', sortable: true, sortMethod: this.handleNameSort }, { prop: 'province', label: '省份', minWidth: '120' }, { prop: 'city', label: '市区', minWidth: '120' }, { prop: 'address', label: '地区', minWidth: '150' }, { prop: 'zip', label: '邮编', minWidth: '120' }], tableData: [{ date: '2016-05-03', name: '王小虎', province: '上海', city: '普陀区', address: '上海市普陀区金沙江路 1518 弄', zip: 200333 }, { date: '2016-05-02', name: '王小虎', province: '上海', city: '普陀区', address: '上海市普陀区金沙江路 1518 弄', zip: 200333 }, { date: '2016-05-04', name: '王小虎', province: '上海', city: '普陀区', address: '上海市普陀区金沙江路 1518 弄', zip: 200333 }, { date: '2016-05-01', name: '王小虎', province: '上海', city: '普陀区', address: '上海市普陀区金沙江路 1518 弄', zip: 200333 }, { date: '2016-05-08', name: '王小虎', province: '上海', city: '普陀区', address: '上海市普陀区金沙江路 1518 弄', zip: 200333 }, { date: '2016-05-06', name: '王小虎', province: '上海', city: '普陀区', address: '上海市普陀区金沙江路 1518 弄', zip: 200333 }] } }, methods: { handleNameSort () { console.log('handleNameSort') } }, components: { wTable } } </script>
Lecture recommandée :
Analyse de cas pratique du composant Progressbar
Comment optimiser le projet Vue
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!