tree.mjs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from "../../../constants/event.mjs";
  2. import { isEmpty, isFunction } from "../../../utils/types.mjs";
  3. import { escapeStringRegexp } from "../../../utils/strings.mjs";
  4. import { ElTree } from "../../tree/index.mjs";
  5. import component from "./tree-select-option.mjs";
  6. import { isValidArray, isValidValue, toValidArray, treeEach, treeFind } from "./utils.mjs";
  7. import { isEqual, isNil, pick } from "lodash-unified";
  8. import { computed, nextTick, toRefs, watch } from "vue";
  9. //#region ../../packages/components/tree-select/src/tree.ts
  10. const useTree = (props, { attrs, slots, emit }, { select, tree, key }) => {
  11. watch([() => props.modelValue, tree], () => {
  12. if (props.showCheckbox) nextTick(() => {
  13. const treeInstance = tree.value;
  14. if (treeInstance && !isEqual(treeInstance.getCheckedKeys(), toValidArray(props.modelValue))) treeInstance.setCheckedKeys(toValidArray(props.modelValue));
  15. });
  16. }, {
  17. immediate: true,
  18. deep: true
  19. });
  20. const propsMap = computed(() => ({
  21. value: key.value,
  22. label: "label",
  23. children: "children",
  24. disabled: "disabled",
  25. isLeaf: "isLeaf",
  26. ...props.props
  27. }));
  28. const getNodeValByProp = (prop, data) => {
  29. const propVal = propsMap.value[prop];
  30. if (isFunction(propVal)) return propVal(data, tree.value?.getNode(getNodeValByProp("value", data)));
  31. else return data[propVal];
  32. };
  33. const defaultExpandedParentKeys = toValidArray(props.modelValue).map((value) => {
  34. return treeFind(props.data || [], (data) => getNodeValByProp("value", data) === value, (data) => getNodeValByProp("children", data), (data, index, array, parent) => parent && getNodeValByProp("value", parent));
  35. }).filter((item) => isValidValue(item));
  36. const cacheOptions = computed(() => {
  37. if (!props.renderAfterExpand && !props.lazy) return [];
  38. const options = [];
  39. treeEach(props.data.concat(props.cacheData), (node) => {
  40. const value = getNodeValByProp("value", node);
  41. options.push({
  42. value,
  43. currentLabel: getNodeValByProp("label", node),
  44. isDisabled: getNodeValByProp("disabled", node)
  45. });
  46. }, (data) => getNodeValByProp("children", data));
  47. return options;
  48. });
  49. const getChildCheckedKeys = () => {
  50. return tree.value?.getCheckedKeys().filter((checkedKey) => {
  51. const node = tree.value?.getNode(checkedKey);
  52. return !isNil(node) && isEmpty(node.childNodes);
  53. });
  54. };
  55. const emitChange = (val) => {
  56. if (!isEqual(props.modelValue, val)) emit(CHANGE_EVENT, val);
  57. };
  58. function update(val) {
  59. emit(UPDATE_MODEL_EVENT, val);
  60. emitChange(val);
  61. }
  62. return {
  63. ...pick(toRefs(props), Object.keys(ElTree.props)),
  64. ...attrs,
  65. nodeKey: key,
  66. expandOnClickNode: computed(() => {
  67. return !props.checkStrictly && props.expandOnClickNode;
  68. }),
  69. defaultExpandedKeys: computed(() => {
  70. return props.defaultExpandedKeys ? props.defaultExpandedKeys.concat(defaultExpandedParentKeys) : defaultExpandedParentKeys;
  71. }),
  72. renderContent: (h, { node, data, store }) => {
  73. return h(component, {
  74. value: getNodeValByProp("value", data),
  75. label: getNodeValByProp("label", data),
  76. disabled: getNodeValByProp("disabled", data),
  77. visible: node.visible
  78. }, props.renderContent ? () => props.renderContent(h, {
  79. node,
  80. data,
  81. store
  82. }) : slots.default ? () => slots.default({
  83. node,
  84. data,
  85. store
  86. }) : void 0);
  87. },
  88. filterNodeMethod: (value, data, node) => {
  89. if (props.filterNodeMethod) return props.filterNodeMethod(value, data, node);
  90. if (!value) return true;
  91. return new RegExp(escapeStringRegexp(value), "i").test(getNodeValByProp("label", data) || "");
  92. },
  93. onNodeClick: (data, node, e) => {
  94. attrs.onNodeClick?.(data, node, e);
  95. if (props.showCheckbox && props.checkOnClickNode) return;
  96. if (!props.showCheckbox && (props.checkStrictly || node.isLeaf)) {
  97. if (!getNodeValByProp("disabled", data)) {
  98. const option = select.value?.states.options.get(getNodeValByProp("value", data));
  99. select.value?.handleOptionSelect(option);
  100. }
  101. } else if (props.expandOnClickNode) e.proxy.handleExpandIconClick();
  102. },
  103. onCheck: (data, params) => {
  104. if (!props.showCheckbox) return;
  105. const dataValue = getNodeValByProp("value", data);
  106. const dataMap = {};
  107. treeEach([tree.value.store.root], (node) => dataMap[node.key] = node, (node) => node.childNodes);
  108. const uncachedCheckedKeys = params.checkedKeys;
  109. const cachedKeys = props.multiple ? toValidArray(props.modelValue).filter((item) => !(item in dataMap) && !uncachedCheckedKeys.includes(item)) : [];
  110. const checkedKeys = cachedKeys.concat(uncachedCheckedKeys);
  111. if (props.checkStrictly) update(props.multiple ? checkedKeys : checkedKeys.includes(dataValue) ? dataValue : void 0);
  112. else if (props.multiple) {
  113. const childKeys = getChildCheckedKeys();
  114. update(cachedKeys.concat(childKeys));
  115. } else {
  116. const firstLeaf = treeFind([data], (data) => !isValidArray(getNodeValByProp("children", data)) && !getNodeValByProp("disabled", data), (data) => getNodeValByProp("children", data));
  117. const firstLeafKey = firstLeaf ? getNodeValByProp("value", firstLeaf) : void 0;
  118. const hasCheckedChild = isValidValue(props.modelValue) && !!treeFind([data], (data) => getNodeValByProp("value", data) === props.modelValue, (data) => getNodeValByProp("children", data));
  119. update(firstLeafKey === props.modelValue || hasCheckedChild ? void 0 : firstLeafKey);
  120. }
  121. nextTick(() => {
  122. const checkedKeys = toValidArray(props.modelValue);
  123. tree.value.setCheckedKeys(checkedKeys);
  124. attrs.onCheck?.(data, {
  125. checkedKeys: tree.value.getCheckedKeys(),
  126. checkedNodes: tree.value.getCheckedNodes(),
  127. halfCheckedKeys: tree.value.getHalfCheckedKeys(),
  128. halfCheckedNodes: tree.value.getHalfCheckedNodes()
  129. });
  130. });
  131. select.value?.focus();
  132. },
  133. onNodeExpand: (data, node, e) => {
  134. attrs.onNodeExpand?.(data, node, e);
  135. nextTick(() => {
  136. if (!props.checkStrictly && props.lazy && props.multiple && node.checked) {
  137. const dataMap = {};
  138. const uncachedCheckedKeys = tree.value.getCheckedKeys();
  139. treeEach([tree.value.store.root], (node) => dataMap[node.key] = node, (node) => node.childNodes);
  140. const cachedKeys = toValidArray(props.modelValue).filter((item) => !(item in dataMap) && !uncachedCheckedKeys.includes(item));
  141. const childKeys = getChildCheckedKeys();
  142. update(cachedKeys.concat(childKeys));
  143. }
  144. });
  145. },
  146. cacheOptions
  147. };
  148. };
  149. //#endregion
  150. export { useTree };
  151. //# sourceMappingURL=tree.mjs.map