废话

大家搜索这个基本都知道这个插件是干啥的,那我就不废话了。如果真的有人不晓得的话,点这个: sortable.js中文文档

问题场景

当时产品拿着一个示例给我,我就要做成这样的。
在这里插入图片描述

emmm,我看了下。右边的信号源列表拖拽到左边的显示列表的子元素内。表示那个显示装置接收了哪个信号源。
了解后我向产品表达了自己的理解,你给我的这个拖拽过去后没有显示,用户都不知道拖拽成功没,而且也成功了也可能会出现不晓得拖到哪个去了的情况,要不要拖过去后就显示在显示列表的子元素下面(即投影仪下面)
就像这样
在这里插入图片描述
唉,产品却这样回复我
在这里插入图片描述

唉,好吧。满足他…

第一步 —— 安装插件

安装

npm install sortablejs --save

引入(这里用的局部引入)

import Sortable from 'sortablejs'

不太清楚的,走这: sortable.js中文文档

第二步 —— 使用

先讲下使用方法(这里是从官网拖的案例)

<div id="itxst">
    <div data-id="1">item 1</div>
    <div data-id="2">item 2</div>
    <div data-id="3">item 3</div>
</div>
<script>
    //获取对象
    var el = document.getElementById('itxst');
    //设置配置
    var ops = {
        animation: 1000,
        //拖动结束
        onEnd: function (evt) {
            console.log(evt);
            //获取拖动后的排序
            var arr = sortable.toArray();
            alert(JSON.stringify(arr));
        },};
    //初始化
    var sortable = Sortable.create(el, ops);
</script>

使用起来还是比较简单的,只需要获取节点对象,然后再设置配置,最后进行初始化就完事了。我们用vue的话可以用ref获取节点。关于配置方面我就不细说,不懂得还是走这: sortable.js中文文档

第三步 —— 分析

根据产品的描述来看,我这里其实需要对三个对象进行配置(添加拖拽)在这里插入图片描述
一个是信号源列表,第二、第三分别是投影仪和投影仪2。但是显示这一块是从接口获取的数据,并不是所有的都是2个。好吧,需要添加拖拽的还不止3个。
那么我们就用循环来解决:先通过for循环循环出显示列表,然后在li里面添加ul标签,这里我用的ref,通过left + id值来进行区分(使用id是因为它具有唯一性,不是非要用id)

<ul ref="left">
  <li class="target" :id="item.id" :name="item.name" :value="item.value"
  v-for="(item,index) in matrixDetail.outs" :key="index">
    <div class="normal-row-flex info-card-child">
      <div>{{item.name}}</div>
      <div class="normal-row-flex equipment">
        <img src="@/assets/images/输出2.png" alt="">
      </div>
    </div>
    <ul :ref="'left' + item.id" :id="item.id">
    </ul>
    <div class="drag-up" v-if="dragStatus" :id="item.id+'up'" :name="item.name+'up'" :value="item.value+'up'"></div>
  </li>
</ul>

再通过forEarch进行循环配置

let this_ = this
var sortables = []// 配置数组
// console.log(this.matrixDetail.outs.length)
this.matrixDetail.outs.forEach((item, index) => {
    // console.log(this_.$refs[`left${item.id}`])
    sortables[index] = Sortable.create(this_.$refs[`left${item.id}`][0], {
      group: {
        name: "words",
        // pull: 'clone',
        put: true
      },
      animation: 150, //动画参数
      // 开始拖拽
      onChoose: function (evt) {  
        this_.$emit("handleIfSwipeabl", false)// 这里是为了解决拖拽操作和滑动切换冲突问题的
      },
      // 拖拽结束
      onEnd: function (evt) {
        this_.$emit("handleIfSwipeabl", true)// 这里是为了解决拖拽操作和滑动切换冲突问题的
      },
    })
});

接下来是信号源的代码:
这里注意:给li标签添加 data-id / id 属性(取值就是唯一值)

<ul ref="right">
 <li class="normal-row-flex info-card option" :id="item.id" :name="item.name" :value="item.value" draggable="true"
  v-for="(item,index) in  matrixDetail.ins" :key="index"  :data-id="item.id">
    <div>{{item.name}}</div>
    <div class="normal-row-flex equipment">
      <img src="@/assets/images/输出.png" alt="">
      <div>
        <div class="normal-row-flex equipment-list" v-for="(itm,idx) in item.showItem" :key="idx">
          <span>{{itm}}</span>
          <span class="handle" @click="signalOff(itm,index,idx)">断开</span>
        </div>
      </div>
    </div>
  </li>
</ul>

js逻辑:

  1. 通过 evt.clone.id 获取克隆的元素(拖拽的信号源)的id(就是之前要添加的data-id / id )
  2. 通过 evt.to.id 获取拖拽的目的元素的id(即投影仪)
  3. 根据产品的要求,删掉拖拽过去的元素(看代码)
  4. 通过filter和唯一值过滤出目标元素的所有数据,方便传参
  5. 写好参数,发送请求
 Sortable.create(this.$refs.right, {
   group: {
     name: "words",
     pull: 'clone',
     put: false
   },
   animation: 150, //动画参数
   // 开始拖拽
   onChoose: function (evt) {  
     this_.$emit("handleIfSwipeabl", false)
   },
    // 拖拽结束
   onEnd: function (evt) {
     this_.$emit("handleIfSwipeabl", true)
     //console.log(evt.clone.id)//被拖拽的
     //console.log(evt.to.id)// 拖拽的目的地
     if(evt.to.id){
     	// 根据产品的要求,删掉拖拽过去的元素
       let ul = this_.$refs[`left${evt.to.id}`]
       ul[0].children.forEach((item, index) => {
         ul[0].removeChild(item);
       })

	   // 通过filter和唯一值过滤出目标元素的所有数据,方便传参
       let objItem = this_.matrixDetail.ins.filter(item => {
         return item.id == evt.clone.id
       })
       let outItem =  this_.matrixDetail.outs.filter(item => {
         return item.id == evt.to.id
       })
       let obj = {
         inId: objItem[0].id,
         inName: objItem[0].name,
         inValue: objItem[0].value,
         outId: outItem[0].id,
         outName: outItem[0].name,
         outValue: outItem[0].value,
       }

       // 接口
       sendCommandAdd({
           equipmentId: this_.matrixDetail.id,
           command: "switch",
           paramObj: obj
         }).then((res) => {
         if (res.data.status == 1) {
           this_.$dialog.alert({
             message: "切换完成!",
           })
         } else {
           this_.$dialog.alert({
             message: res.data.message,
           })
         }
       })

     }
     
   }
 })

这样就满足了产品的需求。

Logo

前往低代码交流专区

更多推荐