今回はElement-UI Tableを使ってドラッグ&ドロップ機能を実装する方法を紹介します。 Element-UI Tableを使ってドラッグ&ドロップ機能を実装する場合の注意点は何ですか?一見。
Element-UI の Table コンポーネントは非常に強力ですが、私たちのニーズはさらに強力です...
シンプルで粗雑なレンダリング:
1 データ駆動型
それらはすべてです。 mousedown、mousemove、mouseup イベント
による dom ノードの変更と削除に基づいています
しかし、Vue はデータ駆動型のフロントエンド フレームワークであるため、開発中に dom を操作することは避けるようにしてください
そして Element の Table コンポーネント-UI はカプセル化されています 非常に厳密で、DOM を直接操作すると予期せぬバグが簡単に発生する可能性があります そこで、私の中心的なアイデアは次のとおりです: 配列を通じてテーブル ヘッダー (列) をレンダリングし、配列の順序を変更することで列を変更するリストの並べ替え
テンプレート部分:
<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>
上記のデータはリストデータコレクション、オプションはテーブルコンポーネント構成アイテム、ヘッダーは親コンポーネントによって渡されるテーブルヘッダーデータコレクションです
props: { data: { default: function () { return [] }, type: Array }, header: { default: function () { return [] }, type: Array }, option: { default: function () { return {} }, type: Object } }
設定項目は Element-UI の API に従って削除できます
ただし、コンポーネント内で使用されるパラメーターがいくつかあります:
1 は、header-cell-class-nameにバインドされています。ヘッダー セルにクラスを動的に追加して、ドラッグ中に点線効果を実現する関数。
2. 列キーは、変更する必要があるヘッダー要素の添字を決定するために使用されるヘッダー配列のインデックスにバインドされます
3. render-headerテーブルヘッダーレンダリング関数、カスタマイズを追加するために使用されます。mousemove およびその他の関連イベントを監視するメソッド
2. ドラッグ ステータスを記録しますドラッグ プロセス中にいくつかの重要なパラメータを記録する必要があります:
data () { return { tableHeader: this.header, dragState: { start: -1, // 起始元素的 index end: -1, // 结束元素的 index move: -1, // 移动鼠标时所覆盖的元素 index dragging: false, // 是否正在拖动 direction: undefined // 拖动方向 } } }
さらに、親要素はヘッダーに渡されます。データヘッダーですが、ドラッグは完了しています。このデータは後で変更されます
子コンポーネント内の親要素のデータを直接変更することはお勧めできません。そのため、ヘッダーデータヘッダーをホストするためにここで tableHeader が初期化されます
しかし、ヘッダーを変更できるようにするには、tableHeader も変更に応答することができます。監視ウォッチ watch: {
header (val, oldVal) {
this.tableHeader = val
}
}
Element-UI の Table コンポーネントをカスタマイズして [ドラッグ列幅を変更するためのボーダー]、mousemove、mouseup、mousedown はありません。イベントは公開されます そのため、ヘッダーをカスタマイズし、renderHeader()
メソッド
を使用する必要があるマウス イベント処理関数を手動で追加する必要があります。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'] }) ]) },
3 つのマウス イベントのうち、最初のパラメーターはイベント オブジェクト、2 番目のパラメーターはヘッダー オブジェクトです 対応する処理関数では、対応するヘッダー要素の添字インデックスは column.columnKey を通じて取得できます
empty label ドラッグ中のアニメーションを表示するために使用します (破線)
4. イベント処理マウスが押されたときに、開始列が記録されます。マウスを離すと、終了列が記録されます。ドラッグ方向は、両者の差に基づいて計算されます。
その後、列のドラッグを実現するために、ヘッダーデータが開始列と終了列の位置に従って並べ替えられます。
ドラッグプロセスの処理関数は次のとおりです: // 按下鼠标开始拖动
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
},
このプロセスでは、mousemove イベントを通じて、現在の列のヘッダーのステータスが変更され 、その後、そのクラスが headerCellClassName
headerCellClassName ({column, columnIndex}) { return (columnIndex - 1 === this.dragState.move ? `darg_active_${this.dragState.direction}` : '') }
の助けを借りて動的に変更されます。ヘッダー セル
自分で書いた完全なスタイルを投稿します (sass を使用)コンパイル ツール):<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;
}
}
}
<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>
推奨書籍:
以上がElement-UI テーブルを使用してドラッグ アンド ドロップ機能を実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。