>  기사  >  웹 프론트엔드  >  Element-UI Table을 사용하여 드래그 앤 드롭 기능 구현

Element-UI Table을 사용하여 드래그 앤 드롭 기능 구현

php中世界最好的语言
php中世界最好的语言원래의
2018-06-08 11:17:206364검색

이번에는 Element-UI 테이블을 사용하여 드래그 앤 드롭 기능을 구현하는 방법에 대해 소개하겠습니다. Element-UI 테이블을 사용하여 드래그 앤 드롭 기능을 구현하는 경우 다음은 실제 사례입니다. 봐.

Element-UI의 테이블 구성 요소는 매우 강력하지만 우리의 요구 사항은 훨씬 더 강력합니다...

간단하고 투박한 렌더링:

1. 데이터 기반

전통적인 드래그 효과는 모두 mousedown, mousemove, mouseup 이벤트

를 통해 dom 노드 수정 및 삭제를 기반으로 하지만 Vue는 데이터 기반 프런트엔드 프레임워크이므로 개발 중에 dom 운영을 피해야 합니다

그리고 Element의 Table 구성 요소 -UI는 캡슐화되어 있습니다. 매우 엄격하여 DOM을 직접 조작하면 예측할 수 없는 버그가 쉽게 발생할 수 있습니다.

그래서 내 핵심 아이디어는 다음과 같습니다. 테이블 헤더(열)를 배열을 통해 렌더링한 다음 배열 순서를 수정하여 열을 수정합니다. sorting of the list

템플릿 부분:

 <p class="w-table" :class="{&#39;w-table_moving&#39;: dragState.dragging}">
 <el-table :data="data"
  :border="option.border"
  :height="option.height"
  :max-height="option.maxHeight"
  :style="{ width: parseInt(option.width)+&#39;px&#39; }"
  :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>

위 데이터는 목록 데이터 모음, 옵션은 Table 컴포넌트 구성 항목, header는 상위 컴포넌트에서 전달되는 테이블 헤더 데이터 모음

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.column-key

는 헤더 배열의 인덱스에 바인딩되어 수정이 필요한 헤더 요소의 첨자를 결정하는 데 사용됩니다

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

 watch: {
 header (val, oldVal) {
  this.tableHeader = val
 }
 }

를 추가해야 합니다. 3. 헤더

Element-UI의 Table 구성 요소를 사용자 정의하여 [drag the] 기능을 구현합니다. 열 너비 수정을 위한 테두리], mousemove, mouseup, mousedown이 없습니다. 이벤트가 노출됩니다

따라서 헤더를 사용자 정의하고 마우스 이벤트에 대한 핸들러 함수를 수동으로 추가해야 합니다. 이를 위해서는 renderHeader() 를 사용해야 합니다. method

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']
   })
  ])
 },

세 가지 마우스 이벤트 중 첫 번째 매개변수가 이벤트 객체, 두 번째 매개변수가 헤더 객체입니다.

해당 처리 함수에서 해당 헤더 요소 첨자 인덱스는 columnKey를 통해 얻을 수 있습니다.

빈 라벨 드래그하는 동안 애니메이션을 표시하는 데 사용됩니다(점선)

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 ? &#39;left&#39; : &#39;right&#39; // 判断拖动方向
  this.dragState.move = parseInt(column.columnKey)
 } else {
  this.dragState.direction = undefined
 }
 } else {
 return false
 }
},

// 拖动易位
dragColumn ({start, end, direction}) {
 let tempData = []
 let left = direction === &#39;left&#39;
 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. 드래그 중 점선 효과

이 과정에서 mousemove 이벤트를 통해 현재 열의 헤더 상태가 변경되고

그런 다음 해당 클래스가 headerCellClassName

headerCellClassName ({column, columnIndex}) {
 return (columnIndex - 1 === this.dragState.move ? `darg_active_${this.dragState.direction}` : &#39;&#39;)
}

의 도움으로 동적으로 수정됩니다. 헤더 셀 에 추가되고 이 클래스는 위 항목에 지정됩니다. 빈 태그 점선만 추가하면 됩니다

직접 작성한 전체 스타일을 게시하세요(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;
 }
 }
}

6. 상위 구성 요소 호출

<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>

믿으세요. 이 기사의 사례를 읽은 후, 더 흥미로운 정보를 보려면 PHP 중국어의 다른 관련 기사를 주목하세요. 웹사이트!

추천 자료:

Progressbar 구성 요소 실제 사례 분석

Vue 프로젝트를 최적화하는 방법

위 내용은 Element-UI Table을 사용하여 드래그 앤 드롭 기능 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.