vuedraggable插件在弹框中使用时,遇到了哪些问题

·  阅读 1423

两天前,客户方提出了便捷工作台的需求,通俗点来说,可通过拖拽、增减等操作,将菜单拖入到想放置的模块中,同时可对大模块拖拽排序,最终以配置的模块或菜单,在首页进行展示。该需求,实现逻辑上其实很简单明了,无非是确定拖拽区域,拖拽对象,按照一定规则操作菜单,但在大的功能做完之后,遗留了一些小的bug,这些小bug容易让人遗漏。因此,在这里记录一下。

一、实现流程

目前项目适用框架:vue2+ant-design-vue

拖拽组件:vuedraggable

  • 页面布局

首页以flex布局去实现,完成固定两行,列数自适应的布局。

弹窗采用ant-design提供的模态框组件去封装,同时根据业务需求,接入vuedraggable组件。这里代码比较简单,直接贴图,具体实现不做赘述。

image.png

image.png

二、遇到的问题

  • 2.1、弹框引发滚动穿透

问题描述:在打开的弹窗中,设置滚动区域,当滚动到弹窗底部或头部,同时超出父级元素滚动区域时,会出现父级div同时滚动现象,也就是所谓的滚动穿透。 如何处理:监听弹窗元素滚动开始start方法,在该方法中,将根元素滚动属性隐藏,对弹窗滚动结束end方法监听,恢复根元素的滚动属性。

<draggable @start="start" @end="end"></draggable>

start() {
  // 防止拖动时,滚动穿透
  document.getElementById('app').style.overflow = 'hidden'
},
end() {
  document.getElementById('app').style.overflow = ''
},
复制代码
  • 2.2、关闭弹窗后,首页展示区域局部渲染

问题描述:对弹窗内容操作之后,需要将弹窗中已经拖拽的元素,按照项目需求展示在首页某个区域中,由于vue只会在加载页面时渲染一次,因此关闭弹窗之后,首页区域不会重新渲染,因而出现了展示区域样式混乱现象。 如何处理:vue只有当组件内容获取样式发生改变之后,才会重新进行渲染,因此我们可以为组件设置key属性,key内容为当前时间值,由于时间值随时在改变,因此vue会重新渲染。

<div class="impact-quick-card-container" :key="new Date().getTime()"></div>
复制代码
  • 2.3、拖拽滚动区域

问题描述:需要指定固定区域,进行拖拽操作,如何确认滚动区域? 如何处理:根据vuedraggable文档描述,可以设置handle属性,该属性中定义拖拽的元素,可以为需要退拽的区域dom设置该属性。

  • 2.4、多级元素拖动设计

问题描述:需求为一个多层拖拽效果,即菜单可以拖拽到所属模块,同时所属模块也能互相拖动,用于排序,如何设置多级元素关联关系的元素拖动呢? 如何处理:首先将模块与菜单元素分层,内部菜单之间可拖动,设置group值为menu,外层模块元素区域,设置另外的group属性为module,通过group区别,来控制不同的拖拽分组。

<draggable group="module">
  <div v-for="(item, index) in modules" :key="index">
    <h3>{{ item.modelName }}</h3>
    <draggable group="menu">
      <div v-for="(element, idx) in item.rows" :key="idx" class="move list-group-item ">
        <span class="text" :title="element.benchName">{{ element.benchName }}</span>
        <b class="list-group-item-icon" @click="subtractPage(item.rows, idx, element)">-</b>
      </div>
    </draggable>
  </div>
</draggable>
复制代码
  • 2.5、拖拽时,无法同时滚动

问题描述:当拖拽某个菜单元素且超过当前区域时,弹窗不向下滚动。 如何处理:vuedraggable文档提供了scrollSensitivity属性,用于描述拖拽距离滚动区域多远时,滚动条滚动。给draggable设置该属性,可以处理该问题。

<draggable group="menu" @start="start" :scrollSensitivity="250">
</draggable>
复制代码
  • 2.6、隐形滚动条

问题描述:当出现滚动时,如何将滚动条做的更好看一些,也就是隐形滚动条,有滚动效果,但不出现浏览器原生滚动条。 如何处理:利用内外两层div包裹,通过css控制滚动区域,外层div滚动属性设置为hidden,内层利用position:fixed固定区域,同时设置overflow属性,这里要这与,如果想要隐藏浏览器的原生滚动条,需要设置内层区域高度或宽度高于外层区域。

<div class="impact-quick-card-container" :key="new Date().getTime()">
    <div class="quick-card-container">
    </div>
</div>


<style lang="less" scoped>
.impact-quick-card-container {
  position: relative;
  height: 250px;
  overflow: hidden;
  .quick-card-container {
      display: flex;
      position: absolute;
      width: 100%;
      overflow-x: auto;
      overflow-y: hidden;
    }
}
</style>
复制代码
  • 2.7、flex固定行的布局

问题描述:如何利用flex布局,固定行,列随着设置动态变化。 如何处理:使用flex的column排序,解决不了该问题。只能通过writing-mode来处理。flex根元素设置writing-mode为vertical-lr,表示元素会从上到下垂直排列,其次flex子元素div上,设置writing-mode为horizontal-tb,表示该元素将水平从左到右排列,同时一定要设置子元素的flex宽度,使用50%将行划分为两行。

<div class="wrapper-content">
    <div class="module-wrapper" v-for="(menu, idx) in item.rows" :key="idx">
    </div>
</div>

<style lang="less" scoped>
.wrapper-content {
  display: flex;
  writing-mode: vertical-lr;
  flex-wrap: wrap;
  padding: 15px 10px 5px 10px;
  height: 200px;
  .module-wrapper {
    flex: 0 0 50%;
    writing-mode: horizontal-tb;
  }
}
</style>
复制代码
分类:
开发工具
标签:
收藏成功!
已添加到「」, 点击更改