This is a draggable tree component. This component does not have css, you need to add your style refer to demo. The demo style is less, not difficult. This component doesn't render node. It exposes a node rendering slot. Please refer to the demo for rendering.


npm i vue-draggable-nested-tree



import {DraggableTree} from 'vue-draggable-nested-tree'
// vue-draggable-nested-tree contains Tree, TreeNode, DraggableTree, DraggableTreeNode
// import the component and register it as global or local component


data: [
  {text: 'node 1'},
  {text: 'node 2'},
  {text: 'node 3 undraggable', draggable: false},
  {text: 'node 4'},
  {text: 'node 4 undroppable', droppable: false},
  {text: 'node 5', children: [
    {text: 'node 1'},
    {text: 'node 2', children: [
      {text: 'node 3'},
      {text: 'node 4'},
    {text: 'node 2 undroppable', droppable: false, children: [
      {text: 'node 3'},
      {text: 'node 4'},
    {text: 'node 2', children: [
      {text: 'node 3'},
      {text: 'node 4 undroppable', droppable: false},
    {text: 'node 3'},
    {text: 'node 4'},
    {text: 'node 3'},
    {text: 'node 4'},
    {text: 'node 3'},
    {text: 'node 4'},
    {text: 'node 3'},
    {text: 'node 4'},


Tree(:data="data" draggable crossTree)
  div(slot-scope="{data, level, store}")
      b(v-if="data.children && data.children.length" @click="store.toggleOpen(data)") {{ ? '-' : '+'}} 
      span {{data.text}}


Tree props

// base tree
data: {},
indent: {default: 16},
activatedClass: {default: 'active'},
openedClass: {default: 'open'},
space: {default: 10}, // space between node, unit px
// draggable tree
getTriggerEl: {type: Function}, // get the el trigger drag, default is node self. arguments(nodeVm)
draggable: {}, // is the tree draggable, default false
droppable: {default: true}, // is the tree droppable, default true
crossTree: {}, // can a node of the tree be dragged into other tree, or receive other tree node
ondragstart: {type: Function}, // hook. return false to prevent drag. arguments(node, nodeVm, this, event, draggable helper option, draggable helper store)
ondragend: {type: Function}, // hook. return false to prevent drop. arguments(node, nodeVm, this, event, draggable helper option, draggable helper store)

Tree properties

rootData, // generated by tree
activated: [], // activated nodes
opened: [], // opened nodes
idMapping: {}, // key: node id, value: node

Tree methods

pure(data, withChildren) // return a node data without runtime properties.
activeNode(node, inactiveOld)
toggleActive(node, inactiveOld)
openNode(node, closeOld)
toggleOpen(node, closeOld)

node properties

// base
children: [],
active: false,
style: {},
class: '',
innerStyle: {},
innerClass: '',
innerBackStyle: {},
innerBackClass: {},
// draggable
draggable // default true
droppable // default true

demo css

  border: 1px solid #ccc;
  padding: 20px;
  width: 300px;
  padding: 5px;
  border: 1px solid #ccc;
  cursor: pointer;
  border: 1px dashed #0088F8;
  box-sizing: border-box;
  background: rgba(0, 136, 249, 0.09);
  color: #0088f9;
  text-align: center;
  padding: 0;
  display: flex;
  align-items: center;


See the Pen vue-draggable-nested-tree demo by phphe (@phphe) on CodePen.