다크 모드
ScTree
트리형 UI를 구성할 때 사용하는 컴포넌트입니다. 트리 선택 후 오른쪽 영역에서 수정/삭제가 가능한 형태로 구성되어 있습니다. v-model을 통해 전체 트리 데이터를 바인딩하며, 선택된 노드를 @select 이벤트를 통해 처리할 수 있습니다.
기본 예제
MENU
메뉴 ID
부모 메뉴 ID
메뉴명
vue
<div class="flex gap-5">
<div class="w-[350px]">
<sc-tree ref="treeRef" v-model="tree" @select="onSelect" />
</div>
<div class="flex-1">
<div class="mb-2 text-right">
<sc-button size="small" @click="onSave" :disabled="!['new', 'modify'].includes(status)">
저장
</sc-button>
<sc-button size="small" :disabled="['none'].includes(status)" @click="onDelete">
삭제
</sc-button>
</div>
<sc-validator ref="validator">
<sc-form-box col="1">
<sc-form-item label="메뉴 ID" required>
<sc-text-field v-if="selectNode === null" disabled />
<sc-text-field
v-else
v-model="selectNode.replaceKey"
:rules="[ruleRequired]"
></sc-text-field>
</sc-form-item>
<sc-form-item label="부모 메뉴 ID" required>
<sc-text-field v-if="selectNode === null" disabled />
<sc-text-field v-else v-model="selectNode.parentKey" disabled></sc-text-field>
</sc-form-item>
<sc-form-item label="메뉴명" required>
<sc-text-field v-if="selectNode === null" disabled />
<sc-text-field
v-else
v-model="selectNode.name"
:rules="[ruleRequired, ruleMinLength(selectNode.name, 1)]"
></sc-text-field>
</sc-form-item>
</sc-form-box>
</sc-validator>
</div>
</div>
<script setup>
import { ref } from 'vue';
import { useRules } from '@/hooks/common/useRules.js';
const { ruleRequired, ruleMinLength } = useRules();
// 컴포넌트 참조를 위한 ref
const treeRef = ref(null);
const validator = ref(null);
const selectNode = ref(null);
const status = ref('none'); // none, new, modify
const tree = ref({
treeInfo: {
key: 'MENU',
name: 'MENU',
// searched: false,
// selected: false,
// checked: false,
// hasChild: true,
expanded: false,
// inlineEdit: false,
},
children: [
{
treeInfo: {
key: 'G0',
parentKey: 'MENU',
name: '업무함',
depth: 2,
seq: 10,
searched: false,
selected: false,
checked: false,
hasChild: true,
expanded: false,
inlineEdit: false,
},
children: [
{
treeInfo: {
key: 'G0A012',
parentKey: 'G0',
name: '작성중',
depth: 3,
seq: 10,
searched: false,
selected: false,
checked: false,
hasChild: false,
expanded: false,
inlineEdit: false,
},
children: [],
},
{
treeInfo: {
key: 'G0A016',
parentKey: 'G0',
name: '미결함',
depth: 3,
seq: 20,
searched: false,
selected: false,
checked: false,
hasChild: false,
expanded: false,
inlineEdit: false,
},
children: [],
},
// 생략
],
},
],
});
const onSelect = (node) => {
// 선택한게 없음
if (node === null) {
status.value = 'none';
selectNode.value = null;
return;
}
selectNode.value = {
...node,
replaceKey: node.key,
}; // 직접 할당이 아닌 복사를 해야 key변경시 tree 확인이 필요
if (node.key === '') {
// 신규
status.value = 'new';
} else if (node.key) {
// 수정
status.value = 'modify';
}
};
const onSave = () => {
const isValid = validator.value.validateAll();
if (isValid) {
// 모두 validation이 통과 되었을 경우 로직
console.info('save', selectNode.value);
}
};
const onDelete = () => {
// delete validation check 후 삭제로직 (하위 차일드 존재여부 체크)
treeRef.value.remove(selectNode.value, () => {
// 삭제로직
console.info('API 로 실제 삭제 로직 실행 axios');
});
};
</script>주요 Props
| Prop | 설명 |
|---|---|
v-model | 전체 트리 구조를 바인딩 |
ref="tree" | 삭제 시 내부 remove 호출 가능 |
@select | 트리 노드 선택 이벤트 발생 |
이벤트
| 이벤트명 | 설명 |
|---|---|
@select | 트리 노드를 선택할 때 발생 |
Tree 노드 구조 (treeInfo)
| 속성명 | 설명 |
|---|---|
key | 고유 ID |
parentKey | 부모 노드의 key |
name | 표시될 텍스트 |
depth | 트리의 깊이 정보 |
expanded | 하위 트리 열림 여부 |
selected | 선택 여부 |
hasChild | 자식 존재 여부 |
inlineEdit | 인라인 편집 여부 |

