当前位置:   article > 正文

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

vue 使用draggable拖拽实现响应式侧边栏,拖拽数据悬停在侧边栏分区超一秒时自动切换到对应分区
封装侧边栏组件
<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
引用侧边栏组件页面
<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
演示效果

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/589560
推荐阅读
相关标签
  

闽ICP备14008679号