knowledge-tree.vue 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <template>
  2. <view class="knowledge-tree">
  3. <knowledge-tree-node v-for="item in initializedData" :key="item.id" :node-data="item"
  4. @node-click="handleNodeClick" @start-practice="handleStartPractice">
  5. <template #default>
  6. <slot></slot>
  7. </template>
  8. </knowledge-tree-node>
  9. </view>
  10. </template>
  11. <script lang="ts" setup>
  12. import * as Study from '@/types/study';
  13. import KnowledgeTreeNode from './knowledge-tree-node.vue';
  14. // 定义 emits
  15. const emit = defineEmits(['nodeClick', 'startPractice']);
  16. // 定义 props
  17. const props = defineProps({
  18. treeData: {
  19. type: Array as PropType<Study.KnowledgeNode[]>,
  20. default: () => []
  21. },
  22. });
  23. // 初始化后的数据
  24. const initializedData = ref<Study.KnowledgeNode[]>([]);
  25. // 确保单个项目的必要属性存在
  26. const ensureItemProperties = (item: Study.KnowledgeNode) => {
  27. if (item.isExpanded === undefined) {
  28. item.isExpanded = false;
  29. }
  30. if (item.isLeaf === undefined) {
  31. item.isLeaf = !item.children || item.children.length === 0;
  32. }
  33. // 递归处理子项
  34. item.children?.forEach(child => ensureItemProperties(child));
  35. }
  36. // 初始化数据
  37. const initializeData = (sourceData: Study.KnowledgeNode[]): Study.KnowledgeNode[] => {
  38. return sourceData.map((item, index) => {
  39. const oldItem = initializedData.value[index];
  40. const children = initializeData(item.children || []);
  41. return {
  42. ...item,
  43. isExpanded: item.id === oldItem?.id ? oldItem?.isExpanded ?? false : false,
  44. isLeaf: !item.children || item.children.length === 0,
  45. children
  46. };
  47. });
  48. }
  49. // 处理节点点击事件
  50. const handleNodeClick = (eventData: { node: Study.KnowledgeNode; parent: Study.KnowledgeNode | null }) => {
  51. // 向上传递点击事件
  52. emit('nodeClick', eventData);
  53. };
  54. // 处理开始练习事件
  55. const handleStartPractice = (node: Study.KnowledgeNode) => {
  56. emit('startPractice', node);
  57. };
  58. // 监听 props.treeData 变化,重新初始化数据
  59. watch(() => props.treeData, (newTreeData) => {
  60. initializedData.value = initializeData(newTreeData);
  61. }, {
  62. immediate: true,
  63. deep: true
  64. });
  65. </script>
  66. <style lang="scss" scoped></style>