美文网首页
Vue 也能实现拖拽了 (vuedraggable)

Vue 也能实现拖拽了 (vuedraggable)

作者: 酷酷的凯先生 | 来源:发表于2020-06-17 10:16 被阅读0次

    vuedraggable是标准的组件式封装,并且将可拖动元素放进了 transition-group 上面,过渡动画都比较好。

    如何使用

    第一步: 安装

    npm install vuedraggable --save
    

    第二步: 使用

    (1). value 注入数据源

    <draggable v-model="list" />
    export default {
        data() {
            return {
               list:[
                {name: 'aaa', id:1 },
                {name: 'bbb', id:2 }
              ]
           };
        }
    }
    

    (2). list 注入数据源

    <draggable :list="list" />
    export default {
        data() {
            return {
             list:[
                {name: 'aaa', id:1 },
                {name: 'bbb', id:2 }
              ]
            };
        }
    }
    

    这俩有啥区别呢?
    value注入的,如果发生了拖拽,value的数据并不会跟着变化,list注入的,则会。
    也就是说
    value注入的,后续有无变化都和数据体没关系,它用于只需要展示拖拽效果的地方;
    list注入的,数据体和当前页面上的属性是保持一致的,页面上的顺序变了,内部数组对应的结构体数组的顺序也会重新排列,和显示保持一致。

    注意,它们不能同时出现,只能二选一。

    第二步: 属性设置

    ghost-class 和 handle
    ghost 指的在拖拽体原本位置占坑的那个元素
    ghost-class 就是给占坑元素设置样式:

    <draggable ghost-class="ghost" > </draggable>
    <style scoped>
      .ghost {
          opacity: 0.5;
          background: #c8ebfb;
      }
    </style>
    

    handle 是拖拽的把手,表示拖拽元素指定可拖拽的部分
    正常情况下拖拽元素的整体都是可拖拽的,加了handle之后,只能指定的地方( 加了handle )可以拖拽了,其他地方不能进行拖拽

    <draggable tag="ul" :list="list" class="list-group" handle=".handle">
        <li class="list-group-item" v-for="(item, index) in list" :key="item.name" >
            <i class="fa fa-align-justify handle"></i>
            <span class="text">{{ item.name }} </span>
            <input type="text" class="form-control" v-model="item.text" />
            <i class="fa fa-times close" @click="remove(index)"></i>
        </li>
    </draggable>
    

    tag 和 componentData
    tag 对于一些特定的原生组合标签,例如ul,li或者table,tr还有tr,td之类的,可以指定一个tag,让draggable替换成指定的标签, 如下 draggable 会被替换成 tbody

    <draggable v-model="list" tag="tbody">
        <tr v-for="item in list" :key="item.name">
            <td scope="row">{{ item.id }}</td>
            <td>{{ item.name }}</td>
            <td>{{ item.sport }}</td>
        </tr>
    </draggable>
    

    componentData 和 tag类似,但是是对于那种组合组件的,例如在ElementUI中的折叠面边,el-collapse和el-collapse-item就是这种组合关系

    <el-collapse v-model="activeNames" @change="handleChange">
        <el-collapse-item title="一级" name="1">
            <div>测试001</div>
            <div>测试002</div>
        </el-collapse-item>
        <el-collapse-item title="二级" name="2">
            <div>测试003</div>
            <div>测试004</div>
        </el-collapse-item>
    </el-collapse>
    

    如上转成vuedraggable的话,首先要设置 tag,但是那些 el-collapse上的数据怎么办呢?这时就要通过component-data配置了, 举个栗子

    <draggable tag="el-collapse" :list="list" :component-data="collapseComponentData" >
        <el-collapse-item v-for="item in list" :key="item.id" :title="item.title" :name="item.id" >
            <div v-for="(lign, idx) in item.text" :key="idx">{{ lign }}</div>
        </el-collapse-item>
    </draggable>
    <script>
    export default {
      components: { draggable },
      data() {
          return {
             list: [
              {
               title: "一级",
               id: 1,
               text: [  "测试001",  "测试002" ]
              },
             {
               title: "二级",
               id: 2,
               text: [  "测试003",  "测试004"  ]
            }
         ],
         activeNames: [1],
         collapseComponentData: {
            on: {
             change: this.inputChanged
            },
            props: {
             value: this.activeNames
            }
         }
        };
      },
      methods: {
        inputChanged(val) {
           this.activeNames = val;
         }
      }
    };
    </script>
    

    上面代码中的collapseComponentData就是将原来el-collapse上传递数据的部分抽离出来了,包括事件(on),属性(prop,attr)的设置。

    group 和 clone
    group 一般的用法是用来区分拖拽组的,group名称相同的拖拽组可以互相拖放:

    <draggable class="list-group" :list="list1" group="people" >
        <div class="list-group-item" v-for="(item, index) in list1" :key="element.name" >
            {{ item.name }} -- {{ index }}
        </div>
    </draggable>
    <draggable class="list-group" :list="list2" group="people" >
        <div class="list-group-item" v-for="(item, index) in list2" :key="item.name" >
            {{ item.name }} -- {{ index }}
        </div>
    </draggable>
    

    group 属性还有更详细的配置,如: group="{name:'abc',pull:'clone',put:false}"。
    put 参数比较简单,是用来控制别的地方内容是否可以拖拽到自己这边来。如果设置为false,那么就表示别的地方的内容无法拖拽到自己这边来。
    pull 参数控制的是从当前拽走,放在另外一个地方的行为。默认情况下(设置为true)是你拽到另外一个地方去,当前列表中就会少一个,对方列表多一个。如果设置为'clone',那么当前列表不会减少,同时对方列表多了一个。

    当然你甚至可以配置一个:clone='func',用来控制放入对方列表的内容,举个栗子

    <draggable class="list-group" :list="list1" 
        :group="{name:'people',pull:pullFunction,put:false}" :clone='clone'>
        <div class="list-group-item" v-for="(item, index) in list1" :key="item.name" >
            {{ item.name }} {{ index }}
        </div>
    </draggable>
    <draggable class="list-group" :list="list2" group="people" >
        <div class="list-group-item" v-for="(item, index) in list2" :key="element.name" >
            {{ item.name }} {{ index }}
        </div>
    </draggable>
    export default {
        methods: {
            clone: function(el) {
             return {
                name: el.name + " cloned"
             };
        },
        pullFunction() {
           return Math.random()*10%2 ? "clone" : true;
        }
      }
    };
    

    pull 设置为 true 还是 'clone' 是随机的(pullFunction)?
    如果设置为 true,那么就是当前少一个,对方多一个;
    如果设置为 'clone',同时:clone='func',则会用调用自定义的clone方法,当前不少,对方多一个。

    transition-group 和 animation
    vuedraggable中的动画主要分成两类,
    交换过程的动画:拖拽元素每经过一个内容项,它就会发生动画移动的效果,这个主要是通过animation的设置, 如下

    <draggable class="list-group" :list="list1" :animation='200'>
        <transition-group>
            <div class="list-group-item" v-for="(item, index) in list1" :key="item.name" >
                {{ item.name }} {{ index }}
            </div>
        </transition-group>
    </draggable>\
    

    只有交换的双方才有动画:交换过程中没有动画,但是只是最后真正交换的时候才有动画,这种需要加个class就好了

    <draggable class="list-group" :list="list1" >
        <transition-group name='flip-list'>
            <div class="list-group-item" v-for="(item, index) in list1" :key="item.name" >
                {{ item.name }} {{ index }}
            </div>
        </transition-group>
    </draggable>
    <style>
      .flip-list-move {
        transition: transform 0.5s;
      }
    </style>
    

    给 transition-group 添加一个name属性flip-lis,然后增加一个 flip-lis-move 的样式类就好了

    相关文章

      网友评论

          本文标题:Vue 也能实现拖拽了 (vuedraggable)

          本文链接:https://www.haomeiwen.com/subject/vrnrxktx.html