Vue에서 요소 드래그 효과를 구현하는 방법 소개

한, H5 원생으로 drag & drop

  • draggable = true (필수)
  • ondragstart : 드래그가 시작될 때 트리거됩니다.
  • ondrag : 드래그하는 동안 트리거 됨
  • ondragend : 드래그 종료시 트리거
  • ondragenter : 드래그 한 요소가 대상 영역에 들어갈 때 트리거됩니다.
  • ondragover : 드래그 한 요소가 대상 영역에서 이동할 때 트리거됩니다.
  • ondragleave : 드래그 한 요소가 대상 영역을 벗어날 때 트리거됩니다.
  • ondrop : 마우스를 놓을 때 트리거됩니다.

2. 실제 사례

2.1 드래그 된 요소 축소 가능 패널 (하위 구성 요소)

<template>
  <div>
      <a-collapse @change="handleCollapseChange($event, step, index)" draggable="true" @dragstart.native="dragStart($event, step, index)">
        <a-collapse-panel key="1" :forceRender="true">
          <span slot="header">
            <!--编辑页面使用-->
            <span v-if="(step.sceneStepType === 'HTTP用例') || (step.sceneStepType === 'RPC用例') || (step.sceneStepType === '场景用例')">Step{
   
   {index + 1}}   {
   
   {step.sceneStepName}}</span>
            <span v-if="step.sceneStepType === 'GET请求'">Step{
   
   {index + 1}}
              <a-input style="width: 20%" v-model="step.sceneStepName" @click="handleGetRequestChange($event, step)"></a-input>
            </span>
            <span v-if="step.sceneStepType === '条件' && !step.hasOwnProperty('sceneCaseStepResult')">Step{
   
   {index + 1}}  If
            <a-input style="width: 10%" v-model="step.sceneFirstExpression" @click="handleFirstExpressionChange($event, step)"></a-input>
            <a-select style="width: 10%" v-decorator="['sceneExpressionJudgeCondition',{ initialValue: step.sceneExpressionJudgeCondition, rules: [{message: 'Please select your gender!' }] },]" placeholder="Select a option and change input text above" @change="handleSelectChange($event, step)">
              <a-select-option v-for="item in stepResultVerifyList" :value="item" :key="item">
                {
   
   {item}}
              </a-select-option>
            </a-select>
            <a-input style="width: 10%" v-model="step.sceneSecondExpression" @click="handleSecondExpressionChange($event, step)"></a-input>
          </span>
            <span style="float: right;"><a-icon type="delete" @click="deleteSceneCaseStepById"/></span>
            <!--历史记录查看详情使用-->
            <span v-if="step.hasOwnProperty('interfaceType')">
            <span>Step{
   
   {index + 1}}   {
   
   {step.testpoint}}  <span style="float: right">运行结果:<a-icon v-if="step.result === 'T'" type="check" style="color: green"/><a-icon v-else type="close" style="color: red"/></span></span>
          </span>
            <span v-if="step.sceneStepType === '条件' && step.hasOwnProperty('sceneCaseStepResult')">Step{
   
   {index + 1}}  If
            <a-input style="width: 10%" v-model="step.sceneFirstExpression" @click="handleFirstExpressionChange($event, step)"></a-input>
            <a-select style="width: 10%" v-decorator="['sceneExpressionJudgeCondition',{ initialValue: step.sceneExpressionJudgeCondition, rules: [{message: 'Please select your gender!' }] },]" placeholder="Select a option and change input text above" @change="handleSelectChange($event, step)">
              <a-select-option v-for="item in stepResultVerifyList" :value="item" :key="item">
                {
   
   {item}}
              </a-select-option>
            </a-select>
            <a-input style="width: 10%" v-model="step.sceneSecondExpression" @click="handleSecondExpressionChange($event, step)"></a-input>
            <span>(1 = 01)</span>
            <span style="float: right">判断结果:<a-icon v-if="step.sceneCaseStepResult === 'T'" type="check" style="color: green"/><a-icon v-else type="close" style="color: red"/></span>
          </span>
            <span v-if="step.sceneStepType === '等待'">Step{
   
   {index + 1}} 等待 <a-input style="width: 10%" v-model="step.sceneStepWaitingtime" @click="handleWaitTimeChange($event, step)"></a-input> 毫秒</span>
          </span>
          <!--折叠面板内容-->
          <!--编辑页面使用-->
          <div v-if="step.sceneStepType === 'GET请求' && !step.hasOwnProperty('sceneCaseStepResult')">
            <a-input v-model="step.sceneStepGetUrl" @click="handleGetUrlChange($event, step)"></a-input>
            <br/>
            <scene-case-step-get-request ref="sceneCaseStepGetRequestObj" @fromSceneCaseStepGetRequest="fromSceneCaseStepGetRequest(step, $event)"/>
          </div>
          <!--历史记录查看详情使用-->
          <div v-if="step.hasOwnProperty('interfaceType')">
            <interface-case-debug-common-details ref="interfaceCaseDebugCommonDetailsObj" :caseTotalData="step"/>
          </div>
          <div v-if="step.sceneStepType === 'GET请求' && step.hasOwnProperty('sceneCaseStepResult')">
            <interface-case-debug-common-details ref="interfaceCaseDebugCommonDetailsObj" :caseTotalData="step"/>
          </div>
        </a-collapse-panel>
      </a-collapse>
  </div>
</template>

드래그가 시작될 때 트리거되는 방법은 다음과 같으며, 주요 기능은 드래그되는 요소의 데이터 정보를 상위 컴포넌트로 전달하는 것입니다.

dragStart (e, step, index) {
  console.log('dragStart e', e)
  // e.dataTransfer.setData('my-info', 'hello')
  // e.dataTransfer.setData('my-extra-info', 'world')
  this.$emit('fromSceneCaseCommonStepsPage', step)
 },

2.2 부모 구성 요소

@ dragover.prevent를 추가해야합니다.

<div style="margin: 8px">
   <a-timeline>
       <a-timeline-item v-for="(step, index) in steps" :key="index" @drop="drop($event, step)" @dragover.prevent>
          <scene-case-common-steps-page :step="step" :index="index" @fromSceneCaseCommonStepsPage="fromSceneCaseCommonStepsPage"/>
       </a-timeline-item>
   </a-timeline>
</div>

하위 구성 요소는 데이터를 상위 구성 요소의 개체에 전달합니다.

    fromSceneCaseCommonStepsPage (data) {
      this.dragging = data
    },

드롭이 마우스를 놓을 때 트리거되는이 방법은 주로 요소 위치 교환 기능 을 실현합니다.

   drop (e, step) {
      console.log('drop', e)
      // console.log(e.dataTransfer.getData('my-info'))
      // console.log(e.dataTransfer.getData('my-extra-info'))
      e.dataTransfer.dropEffect = 'move'

      if (step === this.dragging) {
        return
      }
      const newItems = [...this.steps]
      const from = newItems.indexOf(this.dragging)
      const to = newItems.indexOf(step)
      newItems[from] = step
      newItems[to] = this.dragging
      this.steps = newItems
    },

추천

출처blog.csdn.net/sinat_34241861/article/details/113843479