vuedraggable의 실제 사용: 특정 응용 프로그램 시나리오를 결합하여 목록 내 드래그 앤 드롭 정렬, 목록 간 이동, 복사, 소개, 설치, 사용, 함정 및 솔루션을 실현합니다.

배경

먼저 요구사항을 말씀드리자면, 개발 효율성을 높이고 개발 비용과 기술적인 어려움을 줄이기 위해 코드 생성기의 업그레이드된 솔루션인 구성을 통해 코드를 생성하는 로우 코드 방식을 사용합니다.

프런트 엔드 페이지의 경우 시스템 매개변수와 같은 특정 비즈니스 항목, 공통 메뉴는 목록 페이지에 해당하며 상단에는 추가, 삭제, 내보내기 등의 페이지 수준 기능 버튼과 쿼리가 있습니다. 중앙에는 일반적으로 사용되는 몇 가지 쿼리 조건을 배치할 수 있는 영역이 있고, 하단에는 쿼리 결과가 표시되어 행과 열 데이터가 표 형식으로 표시됩니다. 또한, 사용자 조작을 용이하게 하기 위해 결과 테이블의 행 레코드를 자주 조회하고 행 데이터에 대한 삭제, 편집 등의 일부 단축키 버튼을 그림과 같이 마지막 열에 배치합니다. 아래에

여기에 이미지 설명을 삽입하세요.

참고: 위 그림에서 페이지 수준 기능 버튼은 쿼리 영역과 쿼리 결과 사이에 배치됩니다.

위 페이지의 구성을 구현하려면 구성 가능한 4개의 영역, 즉 페이지 버튼, 쿼리 조건, 쿼리 목록 및 행 버튼을 추상화하고 구분해야 합니다. 렌더링은 다음과 같습니다.

여기에 이미지 설명을 삽입하세요.

기술적 솔루션 측면에서는 구성 및 템플릿 기술을 통해 목록 보기 페이지에 대한 프런트엔드 코드의 자동 생성이 달성됩니다.

위의 구성 기능은 버튼 순서, 쿼리 조건 순서, 쿼리 결과 열 순서 등 요소를 정렬하는 기능과, 다른 한편으로는 요소 간 요소 이동을 포함하는 기능입니다. 쿼리에 엔터티 속성을 추가하는 등 목록 또는 쿼리 결과에서. 기존 모드를 사용하는 경우 요소를 선택하고 왼쪽으로 이동, 오른쪽으로 이동 및 기타 버튼을 클릭해야 하는데 이는 직관적이지 않고 조작이 번거롭습니다. 드래그 앤 드롭 작업을 통해 보이는 그대로 결과를 얻을 수 있으며 사용자 경험이 크게 향상됩니다.

Element UI는 대부분의 UI 컨트롤을 제공하지만 실제로 드래그 앤 드롭의 단점이므로 이를 보완하기 위한 추가 컨트롤이 필요합니다. 즉 오늘날의 주인공인 vuedraggable입니다.

소개

Draggable은 드래그 앤 드롭 기능을 구현하는 데 사용되는 Sortable.js 기반의 vue 구성 요소입니다.

특성
  • 터치 장치 지원
  • 텍스트 드래그 및 선택 지원
  • 스마트 스크롤 지원
  • 서로 다른 목록 간 드래그 앤 드롭 지원
  • jQuery를 기반으로 하지 않음
  • 뷰 모델과 동기적으로 새로 고침
  • vue2 전환 애니메이션과 호환 가능
  • 실행 취소 작업 지원
  • 전체 제어가 필요한 경우 모든 변경 사항을 적용할 수 있습니다.
  • 기존 UI 구성 요소와 호환 가능

공식 주소: https://github.com/SortableJS/Vue.Draggable
중국어 버전 문서: https://www.itxst.com/vue-draggable/tutorial.html

설치하다

npm install vuedraggable -S

인용하다

'vuedraggable'에서 드래그 가능 가져오기

실제 전투

다음으로 실용적인 관점에서 기능을 구현하는 방법, 주요 속성과 사용 방법, 주의가 필요한 사항, 함정과 해결책을 소개하겠습니다.

드래그하여 정렬

페이지 수준 기능 버튼을 예로 들면 그 효과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

프론트엔드 소스코드는 다음과 같습니다.

<template>
  <el-row :gutter="20" type="flex">
    <el-col :span="24">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <span>页面按钮配置</span>
          <span style="float:right">
            <el-button style=" padding: 1px 0" icon="el-icon-plus" @click="add" />
            <el-button style=" padding: 1px 0" icon="el-icon-delete" @click="clear" />
          </span>
        </div>
        <draggable v-model="buttonList" :group="group" @sort="updateSort" @update="update">

          <el-row v-for="(item) in buttonList" :key="item.code">
            <el-col>
              <el-tag closable @close="remove(item.id)" @click="modify(item.id)"> {
   
   { item.name }}</el-tag>

            </el-col>
          </el-row>

        </draggable>

        <detail ref="detail" :custom-parent-id="this.$route.query.id" :button-type="$constant.BUTTON_TYPE_PAGE" @ok="handleDetailSave" />
      </el-card>
    </el-col>

  </el-row>

</template>

<script>
import Detail from './detail'
import Draggable from 'vuedraggable'
export default {
  components: { Detail, Draggable },
  data() {
    return {
      entityViewId: '',
      buttonList: [],
      group: {
        name: 'pageButton',
        pull: false,
        put: false
      }
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.entityViewId = this.$route.query.id
      this.query()
    },
    // 新增
    add() {
      this.$refs.detail.add()
    },
    // 修改
    modify(id) {
      this.$refs.detail.modify(id)
    },
    // 移除
    remove(id) {
      this.$confirm('此操作将移除页面按钮, 是否继续?', '确认', {
        type: 'warning'
      }).then(() => {
        this.$api.entityconfig.entityViewButton.remove(id)
          .then(() => {
            this.query()
          })
      }).catch(() => {
        this.$message.info('已取消')
      })
    },
    // 清空
    clear(id) {
      this.$confirm('此操作将移除所有页面按钮,已配置信息丢失且不可恢复,是否继续?', '确认', {
        type: 'warning'
      }).then(() => {
        this.$api.entityconfig.entityViewButton.clear(id)
          .then(() => {
            this.query()
          })
      }).catch(() => {
        this.$message.info('已取消')
      })
    },

    // 加载按钮列表
    query() {
      this.$api.entityconfig.entityViewButton.listByViewAndType(this.entityViewId, this.$constant.BUTTON_TYPE_PAGE).then(res => {
        this.buttonList = res.data
      })
    },

    // 更新次序
    updateSort(evt) {
      evt.preventDefault()
      const sortedButtonList = this.buttonList.map(function (value, index) {
        return { 'index': index, 'code': value.code }
      })
      this.$api.entityconfig.entityViewButton.updateButtonSort(this.entityViewId, sortedButtonList)
    },
    handleDetailSave() {
      this.query()
    }
  }

}

</script>

<style>

</style>

el-row, el-col, el-card, el-tag 등 Element UI의 다양한 컨트롤을 결합한 것으로, vuedraggable과 관련된 핵심 코드는 다음과 같습니다.

 <draggable v-model="buttonList" :group="group" @update="updateSort">
    <el-row v-for="(item) in buttonList" :key="item.code">
      <el-col>
        <el-tag closable @close="remove(item.id)" @click="modify(item.id)"> {
   
   { item.name }}</el-tag>
      </el-col>
    </el-row>
  </draggable>

핵심 속성은 v-model인데, 이는 컴포넌트의 데이터 소스인 객체 배열에 바인딩되는데 이는 Vue의 표준 관행이므로 말할 것도 없습니다.
그룹 속성은 이 컴포넌트만 보면 따로 설정할 필요가 없지만, 글로벌하게 설정하지 않으면 함정이 있으니 나중에 얘기하겠지만 무시해도 됩니다. 여기요.

컴포넌트 정렬과 관련된 두 가지 이벤트가 있는데, 하나는 업데이트이고 다른 하나는 정렬입니다. 어느 것을 사용해야 할까요?
공식 설명인 update: 위치를 변경할 때 발생하는 이벤트, sort: 위치가 변경될 때 발생하는 이벤트와 차이점을 말하기는 어렵습니다.
직접 테스트해보았는데, 현재 시나리오에서는 요소를 드래그하여 순서를 변경하면 두 이벤트가 모두 트리거될 수 있습니다. 데이터 소스 배열에 요소가 추가되거나 삭제되면 두 이벤트 모두 트리거되지 않습니다. 이 시나리오에서는 어느 이벤트나 사용할 수 있습니다. 여기에서는 업데이트 이벤트가 선택됩니다.

  // 更新次序
    updateSort(evt) {
      evt.preventDefault()
      const sortedButtonList = this.buttonList.map(function (value, index) {
        return { 'index': index, 'code': value.code }
      })
      this.$api.entityconfig.entityViewButton.updateButtonSort(this.entityViewId, sortedButtonList)
    },

evt.preventDefault()의 목적은 Firefox와 같은 일부 브라우저가 드래그를 다운로드로 처리하지 못하도록 하는 것입니다.
Vuedraggable은 프런트엔드 정렬 작업을 수행하며 궁극적으로 처리를 위해 백엔드로 전달되어야 합니다. 따라서 다음 줄은 고유한 데이터 인코딩과 현재 인덱스 값을 객체 배열로 처리하고 이를 백엔드로 전달합니다. 백엔드는 정렬 번호를 업데이트하여 순서 조정을 유지합니다.

목록 간 드래그

구현 효과 다이어그램은 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

이것은 실제로 세 가지 vuedraggable 구성 요소의 조합입니다. 가장 바깥쪽 부분은 다음과 같습니다.

<template>
  <el-row :gutter="20" type="flex">
    <el-col :span="5"> <page-button /></el-col>
    <el-col :span="5"> <property-list @getAllPropertyData="getAllPropertyData" @refreshQueryCondition="refreshQueryCondition" @refreshQueryResult="refreshQueryResult" /></el-col>
    <el-col :span="9">
      <el-row :gutter="20" type="flex">
        <el-col :span="24">  <query-area ref="queryCondition" :property-list-data="allPropertyList" /></el-col>
      </el-row>
      <el-row :gutter="20" type="flex">
        <el-col :span="24">  <result-area ref="queryResult" :property-list-data="allPropertyList" /></el-col>
      </el-row>
    </el-col>
    <el-col :span="5"> <row-button /></el-col>
  </el-row>

</template>

각 영역이 독립적인 Vue 페이지로 나뉘어져 있는데, 처음에는 이런 크로스 페이지 목록 간의 요소 이동이 지원되지 않을까 걱정했는데, 실제로 테스트해 보니 문제가 없어서 다행이네요.

공식 문서에 따르면 목록 사이를 드래그하려면 그룹 속성을 설정해야 하며, 그룹은 단일 속성일 수도 있고 객체일 수도 있으며, 객체의 이름 속성이 동일해야 합니다.

//设置方式一,直接设置组名
group:'list'

//设置方式二,object,也可以通过自定义函数function实现复杂的逻辑
group:{
    name:'list',
    pull: true|false| 'clone'|array|function,//是否允许拖出当前组
    put:true|false|array|function,//是否允许拖入当前组
}

내 디자인에서는 엔터티 속성 목록을 엔터티 구성에서 읽어 오른쪽 상단의 쿼리 조건 목록과 오른쪽 하단의 쿼리 결과 목록에 모두 추가할 수 있으므로 설정은 다음과 같습니다.

allPropertyGroup: {
    name: 'list',
    pull: 'clone',
    put: false
  }

name은 그룹 이름이고, 드래그로 요소를 추가하는 것을 비활성화하려면 put이 false입니다.
참고로, 현재 시나리오에서는 pull 속성 값을 clone으로 설정해야 하는데, 이는 현재 요소를 복사하여 대상 목록에 배치하는 것을 의미하며, true로 설정하면 이동과 동일하고, false로 설정하면 동일함을 의미합니다. 현재 목록에서 드래그를 비활성화합니다.

쿼리 조건과 쿼리 결과는 본질적으로 동일하며, 왼쪽의 엔터티 속성 목록에서 드래그한 요소를 받는 방법을 설명하기 위해 쿼리 조건을 예로 들어보겠습니다.

<draggable v-model="queryConditionList" :group="group" style="height:200px" @add="addFromModelProperty" @update="updateSort">
          <el-row v-for="(item) in queryConditionList" :key="item.code">
            <el-col> <el-tag closable @close="remove(item.id)" @click="modify(item.id)">{
   
   { item.name }}</el-tag>
            </el-col>
          </el-row>
        </draggable>

먼저 그룹 속성을 설정합니다. 이름은 왼쪽 목록과 일치해야 하며, 둘 다 list라고 합니다. 현재 목록에서 드래그를 금지하려면 Pull을 false로 설정합니다. 이때 put에는 true를 주어야 한다는 의미입니다. 드래그를 허용합니다.

group: {
        name: 'list',
        pull: false,
        put: true
      }

그 다음 핵심 이벤트는 드래그한 후 발생하는 이벤트인 add입니다. 이 이벤트에 의해 전달되는 evt 매개변수는 매우 크지만 그 안에 배치되는 것은 우리가 기대하는 데이터가 아니라 프런트엔드 UI 요소라는 점에 유의해야 합니다. . 예를 들어 엔터티 속성의 인코딩을 얻고 싶은데, 이 인코딩을 통해 엔터티 속성을 찾은 다음 다른 관련 데이터를 복사하여 쿼리 목록의 라이브러리 테이블에 삽입할 수 있습니다. evt에서는 이 정보를 얻을 수 없습니다. 매개변수.
이때는 나라를 구하기 위해 곡선을 통해 이룬 것이다. evt 매개변수에서 드래그된 요소의 소스 목록에 대한 index oldIndex를 얻을 수 있으며, 이런 방식으로 소스 목록의 바인딩된 데이터 객체와 결합하여 우리가 기대하는 데이터를 얻을 수 있습니다.

// 新增
    addFromModelProperty(evt) {
      const code = this.propertyListData[evt.oldIndex].code
      this.$api.entityconfig.viewQueryCondition.addFromModelProperty(this.entityViewId, code)
        .then(() => this.sort())
    },

이 시나리오에서는 정렬 이벤트와 업데이트 이벤트의 차이점을 테스트할 수 있으며, 다른 목록의 요소를 드래그하면 정렬 이벤트만 발생하고 업데이트는 발생하지 않습니다. 즉, 업데이트 이벤트는 목록 내에서 드래그할 때 순서가 변경될 때만 발생하고, 요소를 드래그할 때도 정렬이 발생합니다.

정렬에는 더 많은 트리거 기회가 있는데 정렬을 사용하지 않고 업데이트를 계속 사용하는 이유는 무엇입니까?
우리 시나리오에서는 정렬이 문제가 있기 때문에 왼쪽의 속성 목록에서 오른쪽의 쿼리 조건으로 엔터티 속성을 드래그하고, 논리적 처리는 먼저 속성을 복사하고 다음을 기반으로 쿼리 조건에 새 레코드 행을 생성하는 것입니다. 인코딩. 드래그된 객체를 드롭하는 즉시 정렬 이벤트가 발생하며 현재 속성 목록과 인덱스 값이 전달됩니다. 이때 데이터 삽입 작업은 아직 완료되지 않았으며 정렬 번호가 업데이트됩니다. 새로 드래그된 요소는 개체가 존재하지 않는다는 예외를 보고합니다. .
어떻게 해결하나요? 사실 이것도 간단합니다. 우리는 정렬을 사용하지 않습니다. 한편으로는 여전히 업데이트를 사용하여 목록 내에서 드래그 정렬을 처리합니다. 다른 한편으로는 드래그로 새 요소를 추가하는 add 이벤트에서 promise 함수는 데이터 삽입이 성공적으로 처리된 후 시퀀스를 업데이트하는 백엔드 작업을 호출합니다.

// 新增
    addFromModelProperty(evt) {
      const code = this.propertyListData[evt.oldIndex].code
      this.$api.entityconfig.viewQueryCondition.addFromModelProperty(this.entityViewId, code)
        .then(() => this.sort())
        }
    },

    // 拖拽结束
    updateSort(evt) {
      evt.preventDefault()
      this.sort()
    },
    // 排序
    sort() {
      const sortedList = this.queryConditionList.map(function (value, index) {
        return { 'index': index, 'code': value.code }
      })
      this.$api.entityconfig.viewQueryCondition.updateSort(this.entityViewId, sortedList)
    },

참고용으로 쿼리 조건 영역의 전체 소스코드를 첨부합니다.

<template>

  <el-row :gutter="20">
    <el-col :span="24">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <span>查询条件</span>
          <span style="float:right">
            <el-button style=" padding: 1px 0" icon="el-icon-plus" @click="add" />
            <el-button style=" padding: 1px 0" icon="el-icon-delete" @click="clear" />

          </span>
        </div>
        <draggable v-model="queryConditionList" :group="group" style="height:200px" @add="addFromModelProperty" @update="updateSort">
          <el-row v-for="(item) in queryConditionList" :key="item.code">
            <el-col> <el-tag closable @close="remove(item.id)" @click="modify(item.id)">{
   
   { item.name }}</el-tag>
            </el-col>
          </el-row>
        </draggable>
      </el-card>
      <detail ref="detail" :custom-parent-id="this.$route.query.id" @ok="handleDetailSave" />
    </el-col>

  </el-row>

</template>

<script>
import Detail from './detail'
import Draggable from 'vuedraggable'

export default {
  components: { Detail, Draggable },
  props: {
    propertyListData: {
      type: Array,
      default: () => [],
      required: false

    }},
  data() {
    return {
      entityViewId: '',
      queryConditionList: [],
      currentConditionId: '',
      group: {
        name: 'list',
        pull: false,
        put: true
      }
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.entityViewId = this.$route.query.id

      this.query()
    },
    // 新增
    add() {
      this.$refs.detail.add()
    },
    // 新增
    addFromModelProperty(evt) {
      const code = this.propertyListData[evt.oldIndex].code
      this.$api.entityconfig.viewQueryCondition.addFromModelProperty(this.entityViewId, code)
        .then(() => this.sort())
    },
    // 修改
    modify(id) {
      this.currentConditionId = id
      this.$refs.detail.modify(this.currentConditionId)
    },
    // 移除
    remove(queryConditionId) {
      this.$confirm('此操作将移除查询条件, 是否继续?', '确认', {
        type: 'warning'
      }).then(() => {
        this.$api.entityconfig.viewQueryCondition.remove(queryConditionId)
          .then(() => {
            this.query()
          })
      }).catch(() => {
        this.$message.info('已取消')
      })
    },

    // 加载列表
    query() {
      this.$api.entityconfig.viewQueryCondition.listByView(this.entityViewId).then(res => {
        this.queryConditionList = res.data
      })
    },
    // 拖拽结束
    updateSort(evt) {
      evt.preventDefault()
      this.sort()
    },
    // 排序
    sort() {
      const sortedList = this.queryConditionList.map(function (value, index) {
        return { 'index': index, 'code': value.code }
      })
      this.$api.entityconfig.viewQueryCondition.updateSort(this.entityViewId, sortedList)
    },
    // 清空
    clear() {
      this.$confirm('此操作将移除所有查询条件,已配置信息丢失且不可恢复,是否继续?', '确认', {
        type: 'warning'
      }).then(() => {
        this.$api.entityconfig.viewQueryCondition.clear(this.entityViewId)
          .then(() => {
            this.query()
          })
      }).catch(() => {
        this.$message.info('已取消')
      })
    },
    handleDetailSave() {
      this.query()
    }
  }

}

</script>

<style>
.el-row {
    margin-bottom: 10px;
  }

</style>

다음으로, 반복되는 속성 추가를 어떻게 처리할 것인지에 대한 문제에 직면합니다.
vuedraggable을 드래그 앤 드롭만 하면 바로 효과를 볼 수 있는데, 예를 들어 왼쪽 엔터티 속성 목록에서 쿼리 조건을 오른쪽으로 드래그 앤 드롭하면 됩니다. 하지만 실제로 이 시나리오에서는 오른쪽의 속성 목록이 이미 존재하는지 여부를 확인해야 하며, 존재하지 않으면 추가를 허용하고, 존재하면 추가하지 않습니다. 백엔드에서의 검증 처리는 작은 사건이라 여기서는 자세히 다루지 않겠고, 프론트엔드에서 어떻게 처리하느냐가 관건이다.

오랫동안 공식 문서를 읽어보니 적당한 컨트롤을 찾을 수 없었습니다. 저도 바이두에서 오랫동안 검색해 보았는데 만족스러운 결과가 없었습니다. 스스로 탐색한 끝에 드디어 move 이벤트가 가능하다는 것을 알게 되었습니다. 사용됩니다. 실제로 이동의 공식 위치 지정은 드래그할 수 있거나 드래그할 수 없는 요소를 사용자 정의하고 제어하고 도킹 허용 여부를 제어하는 ​​데 사용됩니다. 여기서 원하는 것은 도킹 허용 여부를 제어하는 ​​것입니다.

//move回调方法
onMove(e,originalEvent){ 
         console.log(e);
         console.log(originalEvent);
         //false表示阻止拖拽
         return true;
  },  

우선, move는 이벤트임에도 불구하고 @move='move'에 의해 트리거되지 않고 대신 :move='move'를 사용하여 속성 바인딩을 사용한다는 함정이 있는데 이는 다소 비생산적입니다. 한동안 멈춰서 이벤트가 발생하지 않는 것을 발견했는데, 설명서를 자세히 읽어본 후 문제가 여기에 있다는 것을 발견했습니다.

둘째, 우리 시나리오에서는 move 속성이 왼쪽의 Entity 속성 컴포넌트나 오른쪽의 Query Condition 컴포넌트에 바인딩되어 있는데, 도킹 허용 여부에 대한 설명으로 볼 때 오른쪽에 배치해야 할 것으로 보인다. , 실제 테스트 결과 왼쪽에서 오른쪽으로 드래그하면 전혀 트리거되지 않으므로 이 이동은 실제로 소스 목록에 대한 것입니다.

이번에도 실제 테스트 결과 여러 번 트리거하는 데 문제가 있는 것으로 나타났으며 이는 프런트엔드의 이벤트 버블링 메커니즘과 관련이 있는 것으로 의심되었으며 오랫동안 검색한 결과 여전히 트리거하는 방법을 찾을 수 없었습니다. 한 번만. 혹시 이 구덩이를 메우신 분이 계시다면 댓글로 어떻게 처리해야 하는지 알려주시면 감사하겠습니다.

// 移动
    move(e) {
      // TODO 存在触发多次问题    
      const code = e.draggedContext.element.code
      const list = e.relatedContext.list
      const exist = list.some(item => { return item.code === code })
      // if (exist) {
      //   this.$message.info('已存在,请勿重复添加')
      // }


      return !exist
    }

이 이벤트의 좋은 점은 드래그된 요소에 바인딩된 데이터 객체를 가져올 수 있는 e.draggedContext.element와 대상 목록의 데이터. , 둘 사이의 간단한 비교로 반복 추가 여부를 판단할 수 있으며, 그렇다면 메소드는 false를 반환하고 드래그 동작을 종료할 수 있습니다.

2023-04-17 이동의 다중 트리거 최적화
이동 트리거 수를 제한하기 위해 타사 도구 클래스 스로틀이 도입되었습니다. 자세한 내용은 블로그 게시물 https://blog.csdn.net/seawaving/article/ 을 참조하세요. 세부정보/130157163

import {
    
     throttle } from 'lodash';

export default {
    
    
  methods: {
    
    
    handleMove: throttle(function(event) {
    
    
      // 处理拖动事件
    }, 100)
  }
}

다시 돌아가서
이 문제에 대해 생각했는데 루트에서 목록 사이의 드래그 속성을 구현하고 효과를 한 번만 트리거하려면 vuedraggable 구성 요소가 해당 이벤트를 제공해야 합니다. 지정된 위치. 언제 트리거됩니다.

vuedraggable 구성 요소에는 종료 이벤트가 있지만 이 이벤트는 이동과 다릅니다. false를 반환하면 작업이 취소될 수 있지만 확실히 성공합니다. 즉, 프런트 엔드에서 왼쪽 목록의 속성을 오른쪽 목록으로 드래그합니다. 올바른 목록이 존재했는지 여부. 백엔드에서 검증 및 처리하고 오른쪽 목록을 새로 고칠 수는 있지만 처음 나타났다가 사라지는 깜박임이 불가피하며 효과가 좋지 않습니다.

종료 이벤트는 끌기를 취소할 수 없다는 것이 원래 발견되었으므로 이동은 곡선 절약 솔루션으로 사용되었습니다. 따라서 현재의 최적의 해결책은 실제로 스로틀 기능을 사용하여 트리거 수를 줄이는 것입니다. 반복적인 시도 후에 간격을 500ms로 설정하는 것이 더 적절합니다. 이렇게 하면 드래그 동작이 나타나지 않고 트리거 수를 크게 줄일 수 있습니다. 게으른.

그런데 vuedraggable 컴포넌트가 나중에 종료 이벤트를 취소 가능한 이벤트로 변환하여 이 문제가 완벽하게 해결되기를 바랍니다.

마지막으로 예상치 못한 함정에 대해 말씀드리자면, 공식 문서에 따르면 서로 다른 목록 사이를 드래그할 때 그룹 속성을 설정하고 이름 속성이 일치하는지 확인해야 한다고 합니다. 그런데... 테스트 과정에서 우연히 발견한 사실은 다음과 같습니다. 실제로 페이지 수준을 변경할 수 있습니다. 쿼리 조건 목록에 버튼을 드래그 앤 드롭했는데 그룹 이름이 확실히 달랐습니다... 나중에 페이지 버튼의 구성 요소를 패치하고 해당 요소가 쿼리 조건 목록에서 드래그되는 것을 제한해야 했습니다. 이 문제를 해결하기 위한 목록입니다.

group: {
        name: 'pageButton',
        pull: false,
        put: false
      }

2022-12-08 새로운 버그가 테스트되었습니다. 추가 설명을 부탁드립니다.
엔터티 속성 목록에서 속성을 선택하여 쿼리 조건 목록으로 드래그하면 이 단계는 정상적으로 진행되나, 쿼리 조건 목록에서 새로 추가된 속성을 클릭하고 편집창을 열면 해당 데이터를 찾을 수 없다는 오류가 발생합니다. 문제 해결 후 id 필드에 문제가 있습니다. 드래그한 필드의 id는 엔터티 속성입니다. 새 목록에 배치하면 id가 변경되지 않습니다. 그러나 쿼리 조건 목록의 편집 페이지에서는 id를 사용합니다. 데이터를 얻기 위한 id이므로, 객체를 찾을 수 없다는 문제가 있습니다... 이 구덩이는 상대적으로 숨겨져 있습니다.

이유를 찾았고 해결 방법은 상대적으로 쉽습니다. 정렬 방법에서 쿼리 인터페이스를 다시 호출하고 원격에서 데이터를 가져와 목록의 데이터 소스를 덮어씁니다.


    // 排序
    sort() {
    
    
      const sortedList = this.queryConditionList.map(function (value, index) {
    
    
        return {
    
     'index': index, 'code': value.code }
      })
      this.$api.entityconfig.viewQueryCondition.updateSort(this.entityViewId, sortedList).then(() => {
    
    
        this.query()
      })
    },
   // 加载列表
    query() {
    
    
      this.$api.entityconfig.viewQueryCondition.listByView(this.entityViewId).then(res => {
    
    
        this.queryConditionList = res.data
      })
    },
 

추천

출처blog.csdn.net/seawaving/article/details/128083596