vue使用拖拽方式创建结构树

本文实例为大家分享了vue使用拖拽方式创建结构树的具体代码,供大家参考,具体内容如下

在页面中拖拽虚线框中的节点,创建向右的结构树,如下图

记录实现思路:

vueTree.vue

<template>
  <div class="container">
    <div class="node-container">
      <div v-for="(item, index) in nodeList"
           :key="index"
           class="source-node"
           draggable="true"
           @dragstart="dragStart(item)">
        {{ item }}
      </div>
    </div>
    <div class="tree-container"
         @dragover="allowDrop"
         @drop="handleDrop">
      <tree-node v-if="nodeData"
                 ref="node"
                 :nodeData="nodeData"
                 @delete-node="deleteTree" />
    </div>
  </div>
</template>
<script>
import TreeNode from './treeNode.vue'
import { Node } from './config.js'
export default {
  name: 'vue-tree',
  components: {
    TreeNode
  },
  // 后代节点无法获取节点数据,即无法独立创建节点,所以将祖先节点的创建节点方法暴露给后代节点
  provide () {
    return {
      createNode: this.createNode
    }
  },
  data () {
    return {
      nodeList: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
      currNode: null,
      nodeData: null
    }
  },
  methods: {
    // 开始拖拽,获取节点数据
    dragStart (item) {
      this.currNode = item
    },
    // 若未生成跟节点,则允许拖拽
    allowDrop (event) {
      if (!this.nodeData) {
        event.preventDefault()
      }
    },
    // 拖拽结束,生成节点
    handleDrop () {
      if (!this.nodeData) {
        this.nodeData = this.createNode()
      }
    },
    createNode () {
      let node = new Node(this.currNode)
      return node
    },
    // 根节点删除,删除整个树
    deleteTree () {
      this.nodeData = null
    }
  }
}
</script>
<style lang="scss" scoped>
.container {
  padding: 20px;
  width: calc(100% - 40px);
  height: calc(100% - 40px);
  .node-container {
    height: 100px;
    border: 1px dashed red;
    display: flex;
    .source-node {
      width: 50px;
      height: 30px;
      background: #fff;
      border: 1px solid blue;
      text-align: center;
      line-height: 30px;
      margin: 10px;
      cursor: pointer;
    }
  }
  .tree-container {
    height: calc(100% - 122px);
    margin-top: 20px;
  }
}
</style>

config,js

export class Node{
  constructor(name){
    this.name = name,
    this.children = []
  }
}

treeNode.vue

<template>
  <!--
    结构:最外层是node-inner,每个node-inner中有一个node与node-box,node存放当前节点,node-box存放当前节点的全部子节点,当前节点有几个子节点则node-box中就会有几个node-inner,以此循环
      <node-inner>
        <node></node>
        <node-box>
          <node-inner>
            <node></node>
            <node-box>...</node-box>
          </node-inner>
          <node-inner>
            <node></node>
            <node-box>...</node-box>
          </node-inner>
          ...
        </node-box>
      </node-inner>
   -->
  <div class="node-inner">
    <div class="node"
         :class="{ 'drag-over-node': isDragover }"
         @dragover="dragOver"
         @dragleave="dragLeave"
         @drop="nodeDrop">
      <span class="name">{{nodeData.name}}</span>
      <span class="del"
            @click="deleteNode">删除</span>
    </div>
    <div v-show="nodeData.children.length > 0"
         class="node-box">
      <tree-node v-for="(item,index) in nodeData.children"
                 :key="index"
                 :nodeData="item"
                 @delete-node="deleteChild(index)" />
    </div>
  </div>
</template>
<script>
export default {
  name: 'tree-node',
  props: {
    nodeData: {
      type: Object,
      default: () => { }
    }
  },
  // 获取祖先节点传递的数据
  inject: ['createNode'],
  data () {
    return {
      isDragover: false
    }
  },
  methods: {
    // 节点允许拖拽添加子节点
    dragOver (event) {
      event.preventDefault()
      if (!this.isDragover) {
        this.isDragover = true
      }
    },
    dragLeave () {
      if (this.isDragover) {
        this.isDragover = false
      }
    },
    // 为节点添加子节点
    nodeDrop () {
      let node = this.createNode()
      this.nodeData.children.push(node)
      this.isDragover = false
    },
    // 删除当前节点,本质是交给父级删除子节点
    deleteNode () {
      this.$emit("delete-node")
    },
    // 接收删除子节点的指令并执行删除功能
    deleteChild (index) {
      this.nodeData.children.splice(index, 1)
    }
  }
}
</script>
<style lang="scss" scoped>
.node {
  border: 1px solid orange;
  border-radius: 4px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  background-color: #fff;
  height: 36px;
  padding: 0 12px 0 16px;
  line-height: 36px;
  margin-bottom: 10px;
  .name {
    font-size: 16px;
    margin-right: 12px;
  }
  .del {
    color: red;
    font-size: 12px;
    cursor: pointer;
  }
  &.drag-over-node {
    box-shadow: 6px 6px 12px rgba(106, 20, 134, 0.15);
  }
}
.node-box {
  display: inline-flex;
  flex-direction: column;
  .node-inner {
    margin-left: 80px;
    // 连接竖条
    &:not(:last-child):before {
      position: absolute;
      left: -70px;
      top: 22px;
      border: 1px solid orange;
      content: "";
      width: 8px;
      background-color: #fff;
      border-bottom-color: #fff;
      height: 100%;
      border-top-color: #fff;
      z-index: 3;
    }
    // 连接横条
    &:after {
      left: -61px;
      width: 60px;
      content: "";
      position: absolute;
      top: 14px;
      height: 8px;
      border: 1px solid orange;
      content: "";
      background-color: #fff;
      border-right-color: #fff;
      border-left-color: #fff;
      z-index: 3;
    }
    // 最后一个竖条圆滑拐角
    &:nth-last-child(2):before {
      border-bottom-left-radius: 6px;
      border-bottom-color: orange;
    }
    // 第一个横条拉长
    &:first-child:after {
      left: -81px;
      width: 80px;
      z-index: 2;
    }
  }
}
.node-inner {
  position: relative;
}
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于Vue实现可以拖拽的树形表格实例详解

    因业务需求,需要一个树形表格,并且支持拖拽排序,任意未知插入,github搜了下,真不到合适的,大部分树形表格都没有拖拽功能,所以决定自己实现一个.这里分享一下实现过程,项目源代码请看github,插件已打包封装好,发布到npm上 本博文会分为两部分,第一部分为使用方式,第二部分为实现方式 安装方式 npm i drag-tree-table --save-dev 使用方式 import dragTreeTable from 'drag-tree-table'  模版写法 <dragTreeTa

  • vue使用拖拽方式创建结构树

    本文实例为大家分享了vue使用拖拽方式创建结构树的具体代码,供大家参考,具体内容如下 在页面中拖拽虚线框中的节点,创建向右的结构树,如下图 记录实现思路: vueTree.vue <template> <div class="container"> <div class="node-container"> <div v-for="(item, index) in nodeList" :key="

  • 如何以拖拽方式生成Vue用户界面

    目录 前言 一.技术原理 1.1 布局 1.2 组件 1.3 状态 1.4 事件 1.5 工具箱 二.效果演示 总结 前言 前一阵子拜访了一些小伙伴,大家都表示苦前端太久了,需要花费不少时间在前端开发上.本着在不损失灵活性的前提下尽可能提高开发效率的原则,作者尝试在框架内集成了拖拽方式生成Vue用户界面的功能作为补充,以方便快速生成增删改查界面,也可以用于大屏展示及简单的网页制作. 一.技术原理 1.1 布局   目前仅实现了基于vue-grid-layout的网格布局,设计画布上的每个组件动态

  • Vue实现拖拽穿梭框功能四种方式实例详解

    目录 一.使用原生js实现拖拽 二.VUe使用js实现拖拽穿梭框 三.Vue 拖拽组件 vuedraggable 四.Awe-dnd指令封装 一.使用原生js实现拖拽 <html lang="en"> <head> <meta charset="UTF-8" /> <title>Lazyload</title> <style> .drag { background-color: skyblue;

  • 基于Vue实现拖拽效果

    效果图 demo1.gif 分清clientY pageY screenY layerY offsetY的区别 在我们想要做出拖拽这个效果的时候,我们需要分清这几个属性的区别,这几个属性都是计算鼠标点击的偏移值,我们需要对其进行了解才可以继续实现我们的拖拽效果 clientY 指的是距离可视页面左上角的距离 pageY 指的是距离可视页面左上角的距离(不受页面滚动影响) screenY 指的是距离屏幕左上角的距离 layerY 指的是找到它或它父级元素中最近具有定位的左上角距离 offsetY

  • 解决VUE自定义拖拽指令时 onmouseup 与 click事件冲突问题

    功能描述: 如图,右侧悬浮菜单按钮,只支持上下方向拖动,点击时展开或关闭菜单. BUG说明: 鼠标上下方向拖拽,如果松开时鼠标位于悬浮按钮上会默认执行click事件,经验证,click事件与mouse事件的执行顺序为onmousedown =>onmouseup =>onclick,意味着在click事件执行时会与与其相关的mouse事件冲突. 解决方案: 因为click事件执行时间短,所以利用鼠标拖动的时间差作为标志,在拖拽事件中计算鼠标从onmousedown 到onmouseup 所用的

  • vue 实现拖拽动态生成组件的需求

    产品需求 开完产品需求会议,遇到了一个需求,首先页面分成两栏布局,左侧展示数据组件,支持拖拽排序,点击按钮清除组件.右侧支持将组件的缩略图拖拽至左侧生成一个新的组件. 思路 对于动态生成组件来说每一次都要是生成全新的一个组件,那么就可以把 组件放进函数当中 return.在JSX中调用函数,每次调用函数都会返回一个全新的组件.这对React来说非常简单,但是对于Vue来说,直接将组件返回是不可能的.尽管这个 return 写法不适合Vue,但是我们不可否认,思路是非常正确的,所以我们应该考虑一个

  • jquery利用拖拽方式在图片上添加热链接

    本文实例讲述了jquery利用拖拽方式在图片上添加热链接的实现过程,分享给大家供大家参考.具体如下: 运行效果截图如下: 项目的需求,要在一张图片上加不同的链接,比如说,图片是一个套房,里面有沙发,茶几,酒柜,电视柜等,然后在这些物件上加一个超链接,点击后打开相关产品的介绍. 用jquery写了一个在图片添加锚点的功能,实现的原理:一个文本框写入标题,一个文本框写链接,一个添加按钮,一个编辑按钮,当写好内容后点击添中添加,便会在图片的上方出现一个P标签,然后按着鼠标左键拖拽该标签放到相应的地方松

  • vue实现拖拽的简单案例 不超出可视区域

    本文实例为大家分享了vue实现拖拽x效果的具体代码,供大家参考,具体内容如下 实现拖拽之前,先了解几个小常识: 这两种获取鼠标坐标的方法,区别在于基于的对象不同: pageX和pageY获取的是鼠标指针距离文档(HTML)的左上角距离,不会随着滚动条滚动而改变: clientX和clientY获取的是鼠标指针距离可视窗口(不包括上面的地址栏和滑动条)的距离,会随着滚动条滚动而改变: 1.clientX : 是用来获取鼠标点击的位置距离 当前窗口 左边的距离 2.clientY: 是用来获取鼠标点

  • 基于Vue实现拖拽功能

    本文实例为大家分享了Vue实现拖拽功能的具体代码,供大家参考,具体内容如下 效果图: HTML代码: <div id="box"> 位置 <br>x:{{val.x}} <br>y:{{val.y}} <div v-drag="greet" id="drag" :style="style"> //注意这里要通过指令绑定函数将当前元素的位置数据传出来 </div> &l

  • Vue.Draggable拖拽功能的配置使用方法

    本文实例为大家分享了Vue.Draggable拖拽功能的具体代码,供大家参考,具体内容如下 使用cmd命令在项目根目录下下载安装Vue.Draggable npm install vuedraggable 在组件中需要使用的引入 import draggable from 'vuedraggable' 注册组件 components:{ draggable } vue的template代码如 <draggable v-model="itemlis" //开始移动方法 :move=

随机推荐