Vue和原生API结合的方式来实现, 拖拽


    最近接了一个需求,是把一个图片未识别列表,拖拽到详情列表里面相应的位置。详情列表的图片还能通过拖拽调整位置。

    本来我想尝试使用 vuedraggable, 但是发现,通过查看官方demo,和搜索发现 ,vuedraggable 会拖动整个项,难以满足我只想图片被拖动的效果(有可能我没研究透彻)。总之自由度不是很高。后面发现了原生APi。

    HTML5 的原生拖拽 API(Drag and Drop API来实现自定义的拖拽效果。raggable 属性和相应的事件处理程序来控制拖拽的行为。自由度大大提升。@dragstart、@dragover、@dragenter、@dragleave、@drop和@dragend等事件监听器来处理拖拽的不同阶段。话不多说上代码。

<template>
  <div class="page-container">
    <div class="section">
      <div class="left-section">
        <div class="section-title">{{ isEdit ? "修改详情" : "查看详情" }}</div>
        <div class="info-list">
          <div class="list-item">
            <div class="lf_title">学员名称:</div>
            <div class="rt_value">{{ info.name }}</div>
          </div>
          <div class="list-item">
            <div class="lf_title">身份证:</div>
            <div class="rt_value">{{ info.idcard }}</div>
          </div>
          <div
            v-for="(item, index) in recognizedImagesLists"
            :key="item.key"
            class="list-item"
            :draggable="true"
            @dragstart="handleDragStart(index, 1)"
            @dragend="handleDragEnd"
            @dragover="handleDragOver"
            @drop="handleDrop(index, 1)"
          >
            <div class="lf_title nomove">{{ item.label }}:</div>
            <div class="rt_value">
              <template v-if="item.imageUrl">
                <el-image :src="item.imageUrl" style="height: 150px"></el-image>
              </template>

              <template v-if="!item.imageUrl">
                <el-image style="height: 150px;width: 200px;">
                  <div slot="error" class="image-slot">
                    <i
                      class="el-icon-picture-outline"
                      style="fontSize:24px"
                    ></i>
                  </div>
                </el-image>
              </template>
            </div>
          </div>
        </div>
      </div>
      <div class="right-section">
        <div>未识别图片</div>
        <div
          class="img-lists"
          v-if="UnrecognizedImagesLists && UnrecognizedImagesLists.length > 0"
        >
          <div
            class="img-item"
            v-for="(item, index) in UnrecognizedImagesLists"
            :key="index"
            :draggable="true"
            @dragstart="handleDragStart(index, 2)"
            @dragend="handleDragEnd"
            @dragover="handleDragOver"
            @drop="handleDrop(index, 2)"
          >
            <el-image :src="item.imageUrl" style="width: 150px"> </el-image>
          </div>
        </div>
      </div>
    </div>

    <div class="btn-part" v-show="isEdit">
      <el-button @click="saveDetail" type="primary">确认</el-button>
      <el-button @click="isEdit = false">取消</el-button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isEdit: false,
      // 基础信息
      info: {
        name: "邓xx",
        idcard: "44011119xxx25730"
      },
      //已匹配
      recognizedImagesLists: [
        { key: "idcardImg", label: "身份证(照片)", imageUrl: "" },
        {
          key: "cer",
          label: "学历",
          imageUrl: require("../assets/img/temp/cer.png")
        },
        {
          key: "men",
          label: "半身照",
          imageUrl: require("../assets/img/temp/m.png")
        },
        { key: "sign", label: "个人签名", imageUrl: "" }
      ],
      dragData: null,

      //未匹配
      UnrecognizedImagesLists: [
        { id: 1, imageUrl: require("../assets/img/temp/idcard.png") },
        { id: 2, imageUrl: require("../assets/img/temp/qm.png") }
      ]
    };
  },
  created() {
  },
  methods: {
    /**
     * 拖拽开始时的索引 , 记录初始拖拽的index
     * @param {Number} index
     * @param {Number} listindex
     */
    handleDragStart(index, listIndex) {
      this.dragData = {
        index,
        listIndex
      };
    },
    /**
     * 阻止了默认的拖拽行为
     * @param {*} event
     */
    handleDragOver(event) {
      event.preventDefault();
    },
    /**
     * 拖拽中
     * @param {Number} index 结束时的数组下标
     * @param {Number} listindex
     */
    handleDrop(index, listindex) {
      console.log("开始的index", this.dragData.index);
      console.log("结束的index", index);
      if (this.dragData && this.dragData.listIndex) {
        const startIndex = this.dragData.index;
        const startListsIndex = this.dragData.listIndex;
        if (startListsIndex == listindex) {
          //同列拖拽 已识别->已识别
          const tempImageUrl = this.recognizedImagesLists[index].imageUrl;
          this.recognizedImagesLists[
            index
          ].imageUrl = this.recognizedImagesLists[startIndex].imageUrl;
          this.recognizedImagesLists[startIndex].imageUrl = tempImageUrl; //拖拽完成时交换了拖拽项的位置
        } else {
          //异列拖拽 未识别->已识别
          const unImageUrl = this.UnrecognizedImagesLists[startIndex].imageUrl;
          this.UnrecognizedImagesLists.splice(startIndex, 1);
          this.recognizedImagesLists[index].imageUrl = unImageUrl;
        }
      }
    },
    /**
     * 拖拽结束 重置了拖拽索引
     */
    handleDragEnd() {
      this.dragData = null;
    }
  }
};
</script>

<style lang="less" scoped>
.page-container {
  .header-btns {
    padding: 0 50px;
    margin: 20px 0 30px;
    display: -webkit-flex;
    display: flex;
    -webkit-justify-content: space-between;
    justify-content: space-between;
  }
  .section-title {
    font-weight: 600;
  }

  .section {
    display: flex;
    justify-content: space-between;
    .left-section {
      width: 600px;
      .info-list {
        padding-left: 30px;
        width: 100%;
        .list-item {
          display: flex;
          width: 100%;
          margin-block: 20px;
          .lf_title {
            width: 150px;
            text-align: right;
            font-weight: bold;
            flex-shrink: 0;
          }
          .rt_value {
            width: 450px;
          }
        }
      }
    }
    .right-section {
      width: 400px;
      border: 1px solid;
      padding: 20px;
    }
  }

  .btn-part {
    text-align: center;
    margin-top: 50px;
  }
  /deep/ .image-slot {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    background: #f5f7fa;
    color: #909399;
  }
}
</style>

    

声明:BenBonBen博客|版权所有,违者必究|如未注明,均为原创

转载:转载请注明原文链接 - Vue和原生API结合的方式来实现, 拖拽


过去太迟,未来太远,当下最好