tree-node.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <template>
  2. <ul class="m-tree-node" :style="nodeStyle">
  3. <div
  4. :class="[
  5. 'm-tree-node__content'
  6. ]"
  7. @click.stop="handleToggle(items)">
  8. <span :class="expandIconClass">
  9. <i class="iconfont" :class="iconClass"></i>
  10. </span>
  11. <m-checkbox
  12. class="m-tree-node-checkbox"
  13. v-if="showCheckbox"
  14. v-model="items.isChecked"
  15. :indeterminate="items.indeterminate"
  16. :disabled="items.disabled"
  17. @change="handleCheckChange">
  18. </m-checkbox>
  19. <!-- <span>{{items.label}}</span> -->
  20. <nodeContent
  21. :data="items"
  22. :render-content="renderContent"
  23. :parent-data="parentData"
  24. />
  25. </div>
  26. <mCollapseTransition :duration="0.3" animate="linear">
  27. <div class="m-tree-ul-box" v-if="isShow" v-show="items.isOpen">
  28. <tree-node
  29. v-for="(it,j) in items.children"
  30. :key="j"
  31. :items="it"
  32. :label="label"
  33. :children="children"
  34. :show-checkbox="showCheckbox"
  35. :index="index+1"
  36. :node-key="nodeKey"
  37. :default-expanded-keys="defaultExpandedKeys"
  38. :default-checked-keys="defaultCheckedKeys"
  39. :default-expand-all="defaultExpandAll"
  40. :render-content="renderContent"
  41. :parent-data="items.children">
  42. </tree-node>
  43. </div>
  44. </mCollapseTransition>
  45. </ul>
  46. </template>
  47. <script>
  48. export default {
  49. name: "mTreeNode"
  50. };
  51. </script>
  52. <script setup>
  53. import { ref, computed, onMounted, watch, inject,nextTick } from "vue";
  54. import nodeContent from './node-content.vue';
  55. import mCollapseTransition from '../../collapse-transition';
  56. const props = defineProps({
  57. items:{
  58. type: Object,
  59. default:()=>{}
  60. },
  61. label: String,
  62. children: String,
  63. showCheckbox: Boolean,
  64. index: Number,
  65. nodeKey: String,
  66. // 默认展开项
  67. defaultExpandedKeys: Array,
  68. // 默认选中项
  69. defaultCheckedKeys: Array,
  70. // 默认展开所有
  71. defaultExpandAll: Boolean,
  72. renderContent: Function,
  73. parentData: Array
  74. })
  75. const checkboxChange = inject('checkboxChange')
  76. const toggleChange = inject('toggle-change')
  77. const checkedChange = inject('checked-change')
  78. onMounted(() => {
  79. _initDefault()
  80. })
  81. watch(()=>props.defaultCheckedKeys,(val) => {
  82. if(val) {
  83. _initDefault()
  84. }
  85. })
  86. const isShow = computed(() => {
  87. return props.items.children && props.items.children.length
  88. })
  89. const nodeStyle = computed(() => {
  90. return {
  91. 'padding-left':props.index * 15 + 'px'
  92. }
  93. })
  94. const expandIconClass = computed(() => {
  95. return [
  96. 'm-tree-node__expand-icon',
  97. {
  98. expanded: props.items.isOpen
  99. }
  100. ]
  101. })
  102. const iconClass = computed(() => {
  103. return {
  104. 'icon-arrow-right-filling': props.items.children && props.items.children.length
  105. }
  106. })
  107. const handleToggle = (item) => {
  108. item.isOpen = !item.isOpen
  109. // 展开/收起子节点时触发
  110. toggleChange(item)
  111. }
  112. const handleCheckChange = (val) => {
  113. updateChildChecked(props.items,val) // 设置子级
  114. updateParentChecked() // 设置父级
  115. checkedChange(props.items)
  116. }
  117. // 选中一个节点时,递归地遍历下面所属的所有子节点
  118. const updateChildChecked = (item,val) => {
  119. item.isChecked = val
  120. if(item.children && item.children.length) {
  121. item.children.forEach(el => {
  122. updateChildChecked(el,val)
  123. })
  124. }
  125. }
  126. const updateParentChecked = () => {
  127. nextTick(() => {
  128. checkboxChange && checkboxChange()
  129. })
  130. }
  131. // 初始化默认的展开项和选中项
  132. const _initDefault = () => {
  133. let { items,nodeKey,defaultExpandedKeys,defaultCheckedKeys,defaultExpandAll } = props
  134. const nodeKeyValue = items[nodeKey];
  135. const isExpand = defaultExpandedKeys.includes(nodeKeyValue) || defaultExpandAll;
  136. const isChecked = defaultCheckedKeys.includes(nodeKeyValue);
  137. items.isOpen = isExpand
  138. items.isChecked = isChecked
  139. nextTick(() => {
  140. // 设置默认节点,需要默认勾选对应的所有子节点
  141. if (isChecked) {
  142. updateChildChecked(props.items, isChecked);
  143. }
  144. updateParentChecked();
  145. })
  146. }
  147. </script>
  148. <style lang="scss" scoped>
  149. @import '../../../styles/components/tree.scss';
  150. </style>