u-tree.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <template>
  2. <view class="u-tree">
  3. <tree-node
  4. v-for="node in treeData"
  5. :key="node[props.nodeKey]"
  6. :node="node"
  7. :props="props"
  8. :show-checkbox="showCheckbox"
  9. :check-strictly="checkStrictly"
  10. :expand-on-click-node="expandOnClickNode"
  11. @node-click="handleNodeClick"
  12. @check-change="$emit('check-change', $event)">
  13. <template #default="{ nodeData, level }">
  14. <slot :node="nodeData" :level="level"></slot>
  15. </template>
  16. </tree-node>
  17. </view>
  18. </template>
  19. <script>
  20. import TreeNode from './tree-node.vue';
  21. export default {
  22. name: 'u-tree',
  23. components: { TreeNode },
  24. props: {
  25. data: {
  26. type: Array,
  27. required: true
  28. },
  29. props: {
  30. type: Object,
  31. default: () => ({
  32. label: 'label',
  33. children: 'children',
  34. nodeKey: 'id'
  35. })
  36. },
  37. showCheckbox: {
  38. type: Boolean,
  39. default: false
  40. },
  41. defaultExpandAll: {
  42. type: Boolean,
  43. default: false
  44. },
  45. expandOnClickNode: {
  46. type: Boolean,
  47. default: true
  48. },
  49. checkStrictly: {
  50. type: Boolean,
  51. default: false
  52. }
  53. },
  54. data() {
  55. return {
  56. treeData: []
  57. };
  58. },
  59. created() {
  60. this.initTree();
  61. },
  62. watch: {
  63. data: {
  64. handler(newVal) {
  65. this.treeData = JSON.parse(JSON.stringify(newVal));
  66. this.initExpandedState(this.treeData, this.defaultExpandAll);
  67. },
  68. deep: true,
  69. immediate: true
  70. }
  71. },
  72. emits: ['node-click', 'check-change'],
  73. methods: {
  74. initTree() {
  75. this.treeData = JSON.parse(JSON.stringify(this.data));
  76. this.initExpandedState(this.treeData, this.defaultExpandAll);
  77. },
  78. initExpandedState(nodes, expanded) {
  79. nodes.forEach(node => {
  80. node.expanded = expanded;
  81. if (node[this.props.children]) {
  82. this.initExpandedState(node[this.props.children], expanded);
  83. }
  84. });
  85. },
  86. handleNodeClick(node) {
  87. this.$emit('node-click', node);
  88. },
  89. /**
  90. * 直接递归 treeData 获取所有 checked 的节点
  91. */
  92. getCheckedNodes() {
  93. const traverse = (nodes) => {
  94. let result = [];
  95. nodes.forEach(node => {
  96. if (node.checked) {
  97. result.push(node);
  98. }
  99. if (node[this.props.children] && node[this.props.children].length > 0) {
  100. result = result.concat(traverse(node[this.props.children]));
  101. }
  102. });
  103. return result;
  104. };
  105. return traverse(this.treeData);
  106. }
  107. }
  108. };
  109. </script>
  110. <style scoped>
  111. .u-tree {
  112. font-size: 28rpx;
  113. }
  114. </style>