Skip to content

Latest commit

ย 

History

History
272 lines (266 loc) ยท 8.96 KB

README_ko.md

File metadata and controls

272 lines (266 loc) ยท 8.96 KB

vue-draggable-nested-tree vue

์ด ํ”„๋กœ์ ํŠธ๋Š” ๋“œ๋ž˜๊ทธ๊ฐ€ ๊ฐ€๋Šฅํ•œ ํŠธ๋ฆฌ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” css๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๋ฐ๋ชจ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด ๋‹น์‹ ์˜ style์„ ์ถ”๊ฐ€ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ๋ชจ์˜ style์€ ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ„ฐ์น˜

ํ„ฐ์น˜๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค (1๊ฐœ์˜ ์•„์ดํ…œ)

๊ธฐ๋ถ€

ํŽ˜์ดํŒ” | ์•Œ๋ฆฌํŽ˜์ด | ์œ„์ฑ—

๋ชฉ์ฐจ

์„ค์น˜

npm i vue-draggable-nested-tree

์‚ฌ์šฉ

ํ•จ์ˆ˜ import

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

json ๋ฐ์ดํ„ฐ

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'},
  ]},
]

template

Tree(:data="data" draggable crossTree)
  div(slot-scope="{data, store, vm}")
    //- data is node
    //- store is the tree
    //- vm is node Vue instance, you can get node level by vm.level
    template(v-if="!data.isDragPlaceHolder")
      b(v-if="data.children && data.children.length" @click="store.toggleOpen(data)") {{data.open ? '-' : '+'}} 
      span {{data.text}}

์˜ค๋ž˜๋œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์œ„ํ•œ template(eg: IE)

//- slot-scope="{data, store, vm}" may not work in old browsers, replace with slot-scope="slot"
Tree(:data="data" draggable crossTree)
  div(slot-scope="slot")
    //- data is node
    //- store is the tree
    //- vm is node Vue instance, you can get node level by vm.level
    template(v-if="!slot.data.isDragPlaceHolder")
      b(v-if="slot.data.children && slot.data.children.length" @click="slot.store.toggleOpen(slot.data)") {{slot.data.open ? '-' : '+'}} 
      span {{slot.data.text}}

api

'store'๋Š” tree์— ์žˆ๋Š” VM์ž…๋‹ˆ๋‹ค.

Tree props

๊ธฐ๋ณธ - Tree props
// base tree
data: {}, // type Array
indent: {default: 16},
activatedClass: {default: 'active'},
openedClass: {default: 'open'},
space: {default: 10}, // space between node, unit px
// draggable tree
preventSelect: {default: true}, // if to prevent drag handler text be selected when drag, excluding input and textarea
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

ํ›… - Tree props
ondragstart: {type: Function}, // hook. return false to prevent drag. arguments(node, draggableHelperInfo)
ondragend: {type: Function}, // hook. return false to prevent drop. arguments(node, draggableHelperInfo)

draggableHelperInfo

{event, options, store}

Tree properties

// base
rootData, // generated by tree
// draggable
dplh, // drag placeholder. globally unique.
trees, // array, all trees in the app. globally unique.

Tree ์ด๋ฒคํŠธ

// store is the tree vm
drag(node), // on drag start.
drop(node, targetTree, oldTree), // after drop.
change(node, targetTree, oldTree), // after drop, only when the node position changed
nodeOpenChanged(node) // on a node is closed or open
  • targetTree์™€ oldTree ๋Š” tree vm์ž…๋‹ˆ๋‹ค.
  • oldTree is ์˜ค์ง cross tree์—์„œ๋งŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์™ธ์—๋Š” null์ž…๋‹ˆ๋‹ค..
  • ๋งŒ์•ฝ cross tree๋ฅผ ์‚ฌ์šฉ์ค‘์ด๋ผ๋ฉด targetTree์™€ oldTree ๋Š” ๋“œ๋กญํ•  ๋•Œ ๊ฐ’์ด ๋ฐ”๋€”๊ฒƒ์ž…๋‹ˆ๋‹ค.

Tree ํ•จ์ˆ˜

pure(node, withChildren, after)
/*
pure
return a node data without runtime properties.(!: property which starts with '_' will be removed)
withChildren: optional. after: Function, optional
the code about after(t is computed node data):
if (after) {
  return after(t, node) || t
}
return t
*/
getNodeById(id)
getActivated()
getOpened()
activeNode(node, inactiveOld)
toggleActive(node, inactiveOld)
openNode(node, closeOld)
toggleOpen(node, closeOld)
// follow methods are easy, so I paste their soure code
getPureData(after) { return this.pure(this.rootData, true, after).children } // after: Function, optional
deleteNode(node) { return hp.arrayRemove(node.parent.children, node) }
// add node: like array. eg: node.children.push(newNodeData)
// update node: just assign to the node properties directly
isNodeDraggable(node)
isNodeDroppable(node)

node ์†์„ฑ

// base
_id
_vm
parent
children: [],
open,
active: false,
style: {},
class: '',
innerStyle: {},
innerClass: '',
innerBackStyle: {},
innerBackClass: {},
// draggable
draggable // default true. Please check 'draggable & droppable' below
droppable // default true. Please check 'draggable & droppable' below
isDragPlaceHolder

node์˜ ์•„๋ž˜ ์†์„ฑ ์˜ˆ์ œ

node._vm // vm
node._vm.level // ๋…ธ๋“œ ๋ ˆ๋ฒจ
node._vm.store // ํŠธ๋ฆฌ
node.parent._vm // ๋ถ€๋ชจ node vm
node._vm.store

๊ธฐํƒ€

๋ฐ๋ชจ css

.he-tree{
  border: 1px solid #ccc;
  padding: 20px;
  width: 300px;
}
.tree-node{
}
.tree-node-inner{
  padding: 5px;
  border: 1px solid #ccc;
  cursor: pointer;
}
.draggable-placeholder{
}
.draggable-placeholder-inner{
  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;
}

์˜ˆ์ œ

์ด ํŒจํ‚ค์ง€๋ฅผ cloneํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ ,

npm install
npm run dev

draggable & droppable

ํ•œ๊ฐœ์˜ node๋Š” ๊ธฐ๋ณธ์œผ๋กœ ๋“œ๋ž˜๊ทธ&๋“œ๋ž์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์€ node์˜ ์†์„ฑ์„ ๋“œ๋ž˜๊ทธ&๋“œ๋ž์œผ๋กœ ์„ค์ • ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” 'drag'์ด๋ฒคํŠธ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋‹ค๊ฐ€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋“œ๋ž˜๊ทธ ํ˜น์€ ๋“œ๋ž์†์„ฑ์œผ๋กœ ์„ธํŒ…ํ•˜๋Š”๊ฒƒ์ž…๋‹ˆ๋‹ค.

Traverse tree

๋‚˜์˜ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ tree-helper๋ฅผ ์ถ”์ฒœํ•œ๋‹ค.. ๊ทธ๊ฒƒ์€ 2๊ฐ€์ง€์˜ ๊ฐ€๋กœํŠธ๋ฆฌ๋ฅผ ์ง€์›ํ•œ๋‹ค: depthFirstSearch, breadthFirstSearch.

draggable library

draggable-helper ๋“œ๋ž˜๊ทธ๋ฅผ ์œ„ํ•œ ์ œ๊ฐ€ ๊ฐœ๋ฐœํ•œ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋“œ๋ž˜๊ทธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋„์›€์ด ๋ ๊ฒƒ์ž…๋‹ˆ๋‹ค.