vue 使用draggable拖拽实现响应式侧边栏,拖拽数据悬停在侧边栏分区超一秒时自动切换到对应分区

14 篇文章 6 订阅
9 篇文章 0 订阅
封装侧边栏组件
<template>
  <div>
    <transition name="fade">
      <div class="rightNav" v-show="show">
        <div class="sidebar_draggable_right">
          <div class="group_title" :data-code="areaCode" v-for="areaCode in equipmentAreaList" :key="areaCode">
            {{ equipmentAreasObj[areaCode] }}
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script>

export default {
  name: 'sidebarModal',
  props: {
    equipmentAreaList: {
      type: Array,
      default: () => []
    },
    equipmentAreasObj: {
      type: Object,
      default: () => ({})
    },
  },
  data() {
    return {
      show: false,
      hoverStartTime: null,
      hoverTime: 0,
      timer: null
    }
  },
  mounted() {
    let drag = document.querySelector('.sidebar_draggable_right');

    //进入元素触发
    drag.ondragenter  = (e) => {
      //先清除hover时的样式
      this.clearHoverClass()
      // 判断是group_title
      if (e.target.dataset.code) {
        // 给放置元素添加样式
        e.target.classList.add('title_hover');
      }
    }

    //悬停触发
    drag.ondragover  = (e) => {
      // 判断是group_title
      if (e.target.dataset.code) {
        if (!this.hoverStartTime) {
          this.hoverStartTime = Date.now();
          this.timer = setInterval(() => {
            this.updateHoverTime(e.target);
          }, 100);
        }
      }
    }

    //离开元素触发
    drag.ondragleave  = (e) => {
      clearInterval(this.timer);
      this.hoverStartTime = null;
      this.hoverTime = 0;
    }
  },
  methods: {
    //打开sidebar
    openSidebar() {
      this.show = true
    },
    //关闭sidebar
    closeSideBar() {
      this.show = false
      //先清除hover时的样式
      this.clearHoverClass()
    },
    //计算拖拽切换区停留超过1s
    updateHoverTime(target) {
      if (this.hoverStartTime) {
        this.hoverTime = (Date.now() - this.hoverStartTime) / 1000;
        if (this.hoverTime > 1) {
          console.log("超过1s", target.dataset.code);
          this.$emit("switchTab", target.dataset.code)
        }
      }
    },
    // 清除hover时的样式
    clearHoverClass() {
      document.querySelectorAll('.title_hover').forEach(ele => ele.classList.remove("title_hover"));
    },
  }
}
</script>

<style scoped lang="less">
.rightNav {
  position: fixed;
  right: 5px;
  top: 45%;
  translate: 0 -50%;
  width: 120px;
  background-color: #fff;
  box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  border-radius: 5px;
  //border: 1px solid #ccc;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  padding: 10px;
}

.sidebar_draggable_right {
  width: 100%;
}

.group_title {
  font-size: 15px;
  //border: 1px solid #ccc;
  margin: 5px 0;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 35px;
  box-shadow: -2px 1px 5px rgba(0, 0, 0, 0.2);
}

.title_hover {
  transform: translateX(-2px) scale(1.07);
  color: #38b55a;
}

//过渡动画
.fade-enter-active,  .fade-leave-active {
  transition: all 0.3s linear;
  transform: translateX(0);
}
.fade-enter,  .fade-leave {
  transform: translateX(100%);
}
.fade-leave-to{
  transform: translateX(100%);
}

</style>
引用侧边栏组件页面
<template>
  <div class="layout">
    <div class="container">
      <div class="left_container">
        <!-- 左侧流转卡工序 -->
        <draggable
          class="draggable_left"
          v-model="dataList"
          :group="group"
          :animation="300"
          data-sheet="X"
          filter=".forbid"
          ghostClass="ghost"
          dragClass="drag"
          chosenClass="chosen"
          @start="leftDragStart"
          :move="leftDragMove"
          @end="leftDragEnd"
        >
          <template>
            <div
              class="operation_card"
              v-for="(operationItem, index) in dataList"
              :key="operationItem.id"
            >
              {{operationItem.partName}}
            </div>
          </template>
        </draggable>
      </div>

      <div class="right_container">
        <Tabs class="right_tabs" type="card" v-model="rightTabsName">
          <TabPane :label="equipmentAreasObj[areaCode]" :name="areaCode" v-for="areaCode in equipmentAreaList">
            <div class="right_content">{{equipmentAreasObj[areaCode]}}</div>
          </TabPane>
        </Tabs>
      </div>
    </div>



    <sidebar-modal ref="sidebarModal":equipmentAreaList="equipmentAreaList" :equipmentAreasObj="equipmentAreasObj" @switchTab="switchTab"></sidebar-modal>
  </div>
</template>

<script>
import draggable from 'vuedraggable';
import sidebarModal from './components/sidebarModal'

export default {
  name: "processDispatching11",
  components: {
    draggable,
    sidebarModal
  },
  data() {
    return {
      group: 'operation',
      rightTabsName: 'A01',
      dataList: [
        {id: '1', partName: '产品1'},
        {id: '2', partName: '产品2'},
        {id: '3', partName: '产品3'},
        {id: '4', partName: '产品4'},
        {id: '5', partName: '产品5'},
        {id: '6', partName: '产品6'},
        {id: '7', partName: '产品7'},
        {id: '8', partName: '产品8'},
      ],
      equipmentAreaList: ['A01', 'A02', 'A03', 'A04', 'A05', 'A06', 'A07', 'A08', 'A09', 'A091', 'A10', 'A11', 'A13', 'A14'],
      equipmentAreasObj: {A01:"一区",A02: "二区", A03: "三区", A04: "3.5区", A05: "四区", A06: "五区", A07: "六区", A08: "七区", A09: "八区", A10: "磁铁封胶", A11: "后段组装", A13: "后道终检", A14: "品质部", A091: "九区", null: "其它",},  //用于存放分组名称  key代表code; value代表name
    }
  },
  methods: {
    //todo: 左侧开始拖拽事件
    leftDragStart() {
      //打开侧边栏
      this.$refs.sidebarModal.openSidebar();
    },
    //todo: 左侧拖拽移动事件
    leftDragMove(e) {
      return true
    },
    //todo: 左侧拖拽结束事件
    leftDragEnd(e) {
      //关闭侧边栏
      this.$refs.sidebarModal.closeSideBar();
      return true
    },
    //切换
    switchTab(tabCode) {
      if(this.rightTabsName == tabCode) {
        return
      }

      console.log('onDragOver', tabCode)
      this.rightTabsName = tabCode
    },

  }
}
</script>

<style scoped lang="less">
@padding-len: 10px;

.layout {
  width: 100%;
  height: 100%;
  background: #edeff3;
  padding:  @padding-len;
}

.container {
  display: flex;
  width: 100%;
  height: 100%;
}

//拖拽样式-----------------------
.draggable_left {
 min-height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

.left_container {
  width: 25%;
  height: 100%;
  background: white;
  margin-right: 10px;
  padding:  @padding-len;
  text-align:center;
}

.operation_card {
  width: 60%;
  height: 50px;
  line-height: 42px;
  border: 1px solid #dfdfdf;
  padding: 4px 8px;
  border-radius: 4px;
  margin-bottom: 8px;
}

.right_container {
  width: 75%;
  height: 100%;
  background: white;
  padding:  @padding-len;
}

.right_content {
  width: 100%;
  height: 800px;
  font-size: 25px;
  font-weight: bold;
}
</style>
演示效果

拖拽响应侧边栏,悬停切换

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值