UNPKG

sard-uniapp

Version:

sard-uniapp 是一套基于 Uniapp + Vue3 框架开发的兼容多端的 UI 组件库

194 lines (193 loc) 6.12 kB
import { computed, inject, reactive, ref, shallowRef, watch, } from 'vue'; import { cascaderOptionsContextSymbol, } from './common'; import { isNumber, isString, setCheckedRecursively, walkAncestor, walkNodes, } from '../../utils'; export function useCascaderTree(props, config) { const { useOptionKeysReturn: { getValue, getLabel, getDisabled, getIsLeaf, getChildren, }, innerValue, } = config; const options = computed(() => props.options || []); const legacyLoadChildren = ref(false); const treeData = ref([]); const originalTreeData = shallowRef([]); const loadStatus = ref('loaded'); const toStateNodes = (options, parent) => { return options.map((option) => { const key = getValue(option); const stateNode = reactive({ label: getLabel(option), value: getValue(option), key, disabled: !!getDisabled(option), parent, isLeaf: !!getIsLeaf(option), depth: parent ? parent.depth + 1 : 0, indeterminate: false, checked: false, selected: false, loadStatus: 'idle', option, }); const children = getChildren(option); if (children) { stateNode.children = toStateNodes(children, stateNode); } treeMap.value[key] = stateNode; return stateNode; }); }; const isLeaf = (node) => { return node.isLeaf || !Array.isArray(node.children); }; const clearSelected = () => { walkNodes(treeData.value, (node) => { node.selected = false; }); }; const setAncestorSelected = (node) => { walkAncestor(node, (node) => { node.selected = true; }); }; const setSelectedByNode = (node) => { clearSelected(); setAncestorSelected(node); }; const clearChecked = () => { walkNodes(treeData.value, (node) => { node.checked = false; node.indeterminate = false; }); }; const setCheckedByNode = (node, checked) => { setCheckedRecursively(node, checked, props.checkStrictly); }; const getCheckedLeaves = () => { const nodes = []; walkNodes(treeData.value, (node) => { if (node.checked && isLeaf(node)) { nodes.push(node); } }); return nodes; }; const getCheckedNodes = () => { const nodes = []; walkNodes(treeData.value, (node) => { if (node.checked) { nodes.push(node); } }); return nodes; }; const getAncestors = (node) => { const nodes = []; walkAncestor(node, (node) => { nodes.unshift(node); }); return nodes; }; const updateChecked = (value) => { clearSelected(); // 多选 if (props.multiple) { clearChecked(); if (Array.isArray(value)) { let lastNode; const maySetChecked = (value) => { if (isString(value) || isNumber(value)) { const node = treeMap.value[value]; if (node) { lastNode = node; setCheckedByNode(node, true); } } }; // 全路径 if (props.allLevels) { value.forEach((item) => { if (Array.isArray(item)) { maySetChecked(item[item.length - 1]); } }); } // 最后一级 else { value.forEach(maySetChecked); } if (lastNode) { setAncestorSelected(lastNode); } } } // 单选 else { const maySetSelected = (value) => { if (isString(value) || isNumber(value)) { const node = treeMap.value[value]; if (node) { setAncestorSelected(node); } } }; // 全路径 if (props.allLevels) { if (Array.isArray(value)) { maySetSelected(value[value.length - 1]); } } // 最后一级 else { maySetSelected(value); } } }; const initialize = async () => { if (props.lazy && props.load) { try { loadStatus.value = 'loading'; const data = await props.load(); loadStatus.value = 'loaded'; initializeTree(data); } catch { loadStatus.value = 'error'; } } else { initializeTree(options.value); } }; const treeMap = shallowRef({}); const initializeTree = (data) => { if (legacyLoadChildren.value) { legacyLoadChildren.value = false; return; } treeMap.value = {}; treeData.value = toStateNodes(data, null); updateChecked(innerValue.value); originalTreeData.value = data; }; watch(options, () => { initializeTree(options.value); }); const optionsContext = inject(cascaderOptionsContextSymbol, null); watch(originalTreeData, () => { if (optionsContext) { optionsContext.set(originalTreeData.value); } }); return { treeData, originalTreeData, loadStatus, legacyLoadChildren, toStateNodes, setSelectedByNode, updateChecked, setCheckedByNode, isLeaf, getCheckedLeaves, getCheckedNodes, getAncestors, initialize, }; }