refactor: tree-select
							parent
							
								
									81c16aba93
								
							
						
					
					
						commit
						8bf14f40ac
					
				|  | @ -1,6 +1,6 @@ | |||
| import type { App, Plugin, VNode, ExtractPropTypes } from 'vue'; | ||||
| import { defineComponent, inject, provide } from 'vue'; | ||||
| import Select, { SelectProps } from '../select'; | ||||
| import Select, { selectProps } from '../select'; | ||||
| import Input from '../input'; | ||||
| import PropTypes from '../_util/vue-types'; | ||||
| import { defaultConfigProvider } from '../config-provider'; | ||||
|  | @ -15,7 +15,7 @@ function isSelectOptionOrSelectOptGroup(child: any): boolean { | |||
| } | ||||
| 
 | ||||
| const autoCompleteProps = { | ||||
|   ...SelectProps(), | ||||
|   ...selectProps(), | ||||
|   dataSource: PropTypes.array, | ||||
|   dropdownMenuStyle: PropTypes.style, | ||||
|   optionLabelProp: PropTypes.string, | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import VcSelect, { SelectProps } from '../select'; | ||||
| import VcSelect, { selectProps } from '../select'; | ||||
| import { getOptionProps, getSlot } from '../_util/props-util'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   inheritAttrs: false, | ||||
|   props: SelectProps(), | ||||
|   props: selectProps(), | ||||
|   Option: VcSelect.Option, | ||||
|   render() { | ||||
|     const selectOptionsProps = getOptionProps(this); | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| import type { App, PropType, Plugin, ExtractPropTypes } from 'vue'; | ||||
| import { computed, defineComponent, ref } from 'vue'; | ||||
| import omit from 'omit.js'; | ||||
| import classNames from '../_util/classNames'; | ||||
| import type { SelectProps as RcSelectProps } from '../vc-select'; | ||||
| import { selectProps as vcSelectProps } from '../vc-select'; | ||||
| import RcSelect, { Option, OptGroup, selectBaseProps } from '../vc-select'; | ||||
| import type { OptionProps as OptionPropsType } from '../vc-select/Option'; | ||||
| import getIcons from './utils/iconUtil'; | ||||
|  | @ -10,6 +9,7 @@ import PropTypes from '../_util/vue-types'; | |||
| import { tuple } from '../_util/type'; | ||||
| import useConfigInject from '../_util/hooks/useConfigInject'; | ||||
| import type { SizeType } from '../config-provider'; | ||||
| import omit from '../_util/omit'; | ||||
| 
 | ||||
| type RawValue = string | number; | ||||
| 
 | ||||
|  | @ -24,24 +24,8 @@ export interface LabeledValue { | |||
| } | ||||
| export type SelectValue = RawValue | RawValue[] | LabeledValue | LabeledValue[] | undefined; | ||||
| 
 | ||||
| interface InternalSelectProps<VT> extends Omit<RcSelectProps<VT>, 'mode'> { | ||||
|   suffixIcon?: any; | ||||
|   itemIcon?: any; | ||||
|   size?: SizeType; | ||||
|   mode?: 'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE'; | ||||
|   bordered?: boolean; | ||||
| } | ||||
| 
 | ||||
| interface SelectPropsTypes<VT> | ||||
|   extends Omit<InternalSelectProps<VT>, 'inputIcon' | 'mode' | 'getInputElement' | 'backfill'> { | ||||
|   mode?: 'multiple' | 'tags'; | ||||
| } | ||||
| export type SelectProps = Partial<ExtractPropTypes<SelectPropsTypes<SelectValue>>>; | ||||
| export const selectProps = () => ({ | ||||
|   ...(omit(selectBaseProps(), ['inputIcon', 'mode', 'getInputElement', 'backfill']) as Omit< | ||||
|     SelectPropsTypes<SelectValue>, | ||||
|     'inputIcon' | 'mode' | 'getInputElement' | 'backfill' | 'class' | 'style' | ||||
|   >), | ||||
|   ...omit(vcSelectProps<SelectValue>(), ['inputIcon', 'mode', 'getInputElement', 'backfill']), | ||||
|   value: { | ||||
|     type: [Array, Object, String, Number] as PropType<SelectValue>, | ||||
|   }, | ||||
|  | @ -58,6 +42,8 @@ export const selectProps = () => ({ | |||
|   choiceTransitionName: PropTypes.string.def(''), | ||||
| }); | ||||
| 
 | ||||
| export type SelectProps = Partial<ExtractPropTypes<ReturnType<typeof selectProps>>>; | ||||
| 
 | ||||
| const Select = defineComponent({ | ||||
|   name: 'ASelect', | ||||
|   Option, | ||||
|  |  | |||
|  | @ -11,8 +11,6 @@ import VcTreeSelect, { | |||
| import classNames from '../_util/classNames'; | ||||
| import initDefaultProps from '../_util/props-util/initDefaultProps'; | ||||
| import type { SizeType } from '../config-provider'; | ||||
| 
 | ||||
| export { TreeData, TreeSelectProps } from './interface'; | ||||
| import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; | ||||
| import CaretDownOutlined from '@ant-design/icons-vue/CaretDownOutlined'; | ||||
| import type { DefaultValueType, FieldNames } from '../vc-tree-select/interface'; | ||||
|  | @ -23,6 +21,7 @@ import devWarning from '../vc-util/devWarning'; | |||
| import getIcons from '../select/utils/iconUtil'; | ||||
| import renderSwitcherIcon from '../tree/utils/iconUtil'; | ||||
| import type { AntTreeNodeProps } from '../tree/Tree'; | ||||
| import { warning } from '../vc-util/warning'; | ||||
| 
 | ||||
| const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => { | ||||
|   if (transitionName !== undefined) { | ||||
|  | @ -53,6 +52,7 @@ export const treeSelectProps = { | |||
|   replaceFields: { type: Object as PropType<FieldNames> }, | ||||
| }; | ||||
| export type TreeSelectProps = Partial<ExtractPropTypes<typeof treeSelectProps>>; | ||||
| 
 | ||||
| const TreeSelect = defineComponent({ | ||||
|   TreeNode, | ||||
|   SHOW_ALL, | ||||
|  | @ -68,8 +68,19 @@ const TreeSelect = defineComponent({ | |||
|     listItemHeight: 26, | ||||
|     bordered: true, | ||||
|   }), | ||||
|   slots: ['placeholder', 'maxTagPlaceholder', 'treeIcon', 'switcherIcon', 'notFoundContent'], | ||||
|   slots: [ | ||||
|     'title', | ||||
|     'placeholder', | ||||
|     'maxTagPlaceholder', | ||||
|     'treeIcon', | ||||
|     'switcherIcon', | ||||
|     'notFoundContent', | ||||
|   ], | ||||
|   setup(props, { attrs, slots, expose, emit }) { | ||||
|     warning( | ||||
|       !(props.treeData === undefined && slots.default), | ||||
|       '`children` of Tree is deprecated. Please use `treeData` instead.', | ||||
|     ); | ||||
|     watchEffect(() => { | ||||
|       devWarning( | ||||
|         props.multiple !== false || !props.treeCheckable, | ||||
|  | @ -212,6 +223,7 @@ const TreeSelect = defineComponent({ | |||
|           onSearch={handleSearch} | ||||
|           onTreeExpand={handleTreeExpand} | ||||
|           v-slots={{ | ||||
|             ...slots, | ||||
|             treeCheckable: () => <span class={`${prefixCls.value}-tree-checkbox-inner`} />, | ||||
|           }} | ||||
|           children={slots.default?.()} | ||||
|  |  | |||
|  | @ -1,65 +0,0 @@ | |||
| import PropTypes, { withUndefined } from '../_util/vue-types'; | ||||
| import { SelectProps } from '../select'; | ||||
| import { tuple } from '../_util/type'; | ||||
| 
 | ||||
| export const TreeData = PropTypes.shape({ | ||||
|   key: PropTypes.string, | ||||
|   value: PropTypes.string, | ||||
|   label: PropTypes.VNodeChild, | ||||
|   slots: PropTypes.object, | ||||
|   children: PropTypes.array, | ||||
| }).loose; | ||||
| 
 | ||||
| export const TreeSelectProps = () => ({ | ||||
|   ...SelectProps(), | ||||
|   autofocus: PropTypes.looseBool, | ||||
|   dropdownStyle: PropTypes.object, | ||||
|   filterTreeNode: withUndefined(PropTypes.oneOfType([Function, Boolean])), | ||||
|   getPopupContainer: PropTypes.func, | ||||
|   labelInValue: PropTypes.looseBool, | ||||
|   loadData: PropTypes.func, | ||||
|   maxTagCount: PropTypes.number, | ||||
|   maxTagPlaceholder: PropTypes.VNodeChild, | ||||
|   value: PropTypes.oneOfType([ | ||||
|     PropTypes.string, | ||||
|     PropTypes.object, | ||||
|     PropTypes.array, | ||||
|     PropTypes.number, | ||||
|   ]), | ||||
|   defaultValue: PropTypes.oneOfType([ | ||||
|     PropTypes.string, | ||||
|     PropTypes.object, | ||||
|     PropTypes.array, | ||||
|     PropTypes.number, | ||||
|   ]), | ||||
|   multiple: PropTypes.looseBool, | ||||
|   notFoundContent: PropTypes.VNodeChild, | ||||
|   searchPlaceholder: PropTypes.string, | ||||
|   searchValue: PropTypes.string, | ||||
|   showCheckedStrategy: PropTypes.oneOf(tuple('SHOW_ALL', 'SHOW_PARENT', 'SHOW_CHILD')), | ||||
|   suffixIcon: PropTypes.VNodeChild, | ||||
|   treeCheckable: PropTypes.looseBool, | ||||
|   treeCheckStrictly: PropTypes.looseBool, | ||||
|   treeData: PropTypes.arrayOf(Object), | ||||
|   treeDataSimpleMode: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, Object])), | ||||
| 
 | ||||
|   dropdownClassName: PropTypes.string, | ||||
|   dropdownMatchSelectWidth: PropTypes.looseBool, | ||||
|   treeDefaultExpandAll: PropTypes.looseBool, | ||||
|   treeExpandedKeys: PropTypes.array, | ||||
|   treeIcon: PropTypes.looseBool, | ||||
|   treeDefaultExpandedKeys: PropTypes.array, | ||||
|   treeNodeFilterProp: PropTypes.string, | ||||
|   treeNodeLabelProp: PropTypes.string, | ||||
|   replaceFields: PropTypes.object.def({}), | ||||
|   clearIcon: PropTypes.VNodeChild, | ||||
|   removeIcon: PropTypes.VNodeChild, | ||||
| 
 | ||||
|   onSelect: PropTypes.func, | ||||
|   onChange: PropTypes.func, | ||||
|   onSearch: PropTypes.func, | ||||
|   onTreeExpand: PropTypes.func, | ||||
|   'onUpdate:treeExpandedKeys': PropTypes.func, | ||||
|   'onUpdate:searchValue': PropTypes.func, | ||||
|   'onUpdate:value': PropTypes.func, | ||||
| }); | ||||
|  | @ -13,6 +13,7 @@ import useConfigInject from '../_util/hooks/useConfigInject'; | |||
| import renderSwitcherIcon from './utils/iconUtil'; | ||||
| import dropIndicatorRender from './utils/dropIndicator'; | ||||
| import devWarning from '../vc-util/devWarning'; | ||||
| import { warning } from '../vc-util/warning'; | ||||
| 
 | ||||
| export interface AntdTreeNodeAttribute { | ||||
|   eventKey: string; | ||||
|  | @ -153,6 +154,10 @@ export default defineComponent({ | |||
|   ], | ||||
|   TreeNode, | ||||
|   setup(props, { attrs, expose, emit, slots }) { | ||||
|     warning( | ||||
|       !(props.treeData === undefined && slots.default), | ||||
|       '`children` of Tree is deprecated. Please use `treeData` instead.', | ||||
|     ); | ||||
|     const { prefixCls, direction, virtual } = useConfigInject('tree', props); | ||||
|     const treeRef = ref(); | ||||
|     expose({ | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ import { | |||
|   flattenOptions, | ||||
|   fillOptionsWithMissingValue, | ||||
| } from './utils/valueUtil'; | ||||
| import type { SelectProps } from './generate'; | ||||
| import { selectBaseProps, SelectProps } from './generate'; | ||||
| import generateSelector from './generate'; | ||||
| import type { DefaultValueType } from './interface/generator'; | ||||
| import warningProps from './utils/warningPropsUtil'; | ||||
|  | @ -68,6 +68,10 @@ export type ExportedSelectProps<T extends DefaultValueType = DefaultValueType> = | |||
|   T | ||||
| >; | ||||
| 
 | ||||
| export function selectProps<T>() { | ||||
|   return selectBaseProps<SelectOptionsType[number], T>(); | ||||
| } | ||||
| 
 | ||||
| const Select = defineComponent({ | ||||
|   name: 'Select', | ||||
|   inheritAttrs: false, | ||||
|  |  | |||
|  | @ -2,8 +2,9 @@ import pickAttrs from '../../_util/pickAttrs'; | |||
| import Input from './Input'; | ||||
| import type { InnerSelectorProps } from './interface'; | ||||
| import type { VNodeChild } from 'vue'; | ||||
| import { computed, defineComponent, Fragment, ref, watch } from 'vue'; | ||||
| import { computed, defineComponent, ref, watch } from 'vue'; | ||||
| import PropTypes from '../../_util/vue-types'; | ||||
| import { useInjectTreeSelectContext } from 'ant-design-vue/es/vc-tree-select/Context'; | ||||
| 
 | ||||
| interface SelectorProps extends InnerSelectorProps { | ||||
|   inputElement: VNodeChild; | ||||
|  | @ -50,6 +51,7 @@ const SingleSelector = defineComponent<SelectorProps>({ | |||
|       } | ||||
|       return inputValue; | ||||
|     }); | ||||
|     const treeSelectContext = useInjectTreeSelectContext(); | ||||
|     watch( | ||||
|       [combobox, () => props.activeValue], | ||||
|       () => { | ||||
|  | @ -94,6 +96,12 @@ const SingleSelector = defineComponent<SelectorProps>({ | |||
|         onInputCompositionEnd, | ||||
|       } = props; | ||||
|       const item = values[0]; | ||||
|       let slotTitle = null; | ||||
|       if (treeSelectContext.value.slots) { | ||||
|         slotTitle = | ||||
|           treeSelectContext.value.slots[item?.option?.data?.slots?.title] || | ||||
|           treeSelectContext.value.slots.title; | ||||
|       } | ||||
|       return ( | ||||
|         <> | ||||
|           <span class={`${prefixCls}-selection-search`}> | ||||
|  | @ -126,7 +134,8 @@ const SingleSelector = defineComponent<SelectorProps>({ | |||
|           {/* Display value */} | ||||
|           {!combobox.value && item && !hasTextInput.value && ( | ||||
|             <span class={`${prefixCls}-selection-item`} title={title.value}> | ||||
|               <Fragment key={item.key || item.value}>{item.label}</Fragment> | ||||
|               {/* <Fragment key={item.key || item.value}>{item.label}</Fragment> */} | ||||
|               {slotTitle?.(item.option?.data) || item.label} | ||||
|             </span> | ||||
|           )} | ||||
| 
 | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ export function selectBaseProps<OptionType, ValueType>() { | |||
|     defaultOpen: { type: Boolean, default: undefined }, | ||||
|     listHeight: Number, | ||||
|     listItemHeight: Number, | ||||
|     dropdownStyle: { type: Function as PropType<CSSProperties> }, | ||||
|     dropdownStyle: { type: Object as PropType<CSSProperties> }, | ||||
|     dropdownClassName: String, | ||||
|     dropdownMatchSelectWidth: { | ||||
|       type: [Boolean, Number] as PropType<boolean | number>, | ||||
|  | @ -275,7 +275,7 @@ export default function generateSelector< | |||
|     slots: ['option'], | ||||
|     inheritAttrs: false, | ||||
|     props: selectBaseProps<OptionType, DefaultValueType>(), | ||||
|     setup(props) { | ||||
|     setup(props, { expose }) { | ||||
|       const useInternalProps = computed( | ||||
|         () => props.internalProps && props.internalProps.mark === INTERNAL_PROPS_MARK, | ||||
|       ); | ||||
|  | @ -455,10 +455,10 @@ export default function generateSelector< | |||
|             labelInValue: mergedLabelInValue.value, | ||||
|             optionLabelProp: mergedOptionLabelProp.value, | ||||
|           }); | ||||
| 
 | ||||
|           return { | ||||
|             ...displayValue, | ||||
|             disabled: isValueDisabled(val, valueOptions), | ||||
|             option: valueOptions[0], | ||||
|           }; | ||||
|         }); | ||||
| 
 | ||||
|  | @ -947,10 +947,12 @@ export default function generateSelector< | |||
|       const blur = () => { | ||||
|         selectorRef.value.blur(); | ||||
|       }; | ||||
|       return { | ||||
|       expose({ | ||||
|         focus, | ||||
|         blur, | ||||
|         scrollTo: listRef.value?.scrollTo, | ||||
|         scrollTo: (...args: any[]) => listRef.value?.scrollTo(...args), | ||||
|       }); | ||||
|       return { | ||||
|         tokenWithEnter, | ||||
|         mockFocused, | ||||
|         mergedId, | ||||
|  | @ -1139,7 +1141,7 @@ export default function generateSelector< | |||
|           menuItemSelectedIcon={menuItemSelectedIcon} | ||||
|           virtual={virtual !== false && dropdownMatchSelectWidth !== false} | ||||
|           onMouseenter={onPopupMouseEnter} | ||||
|           v-slots={{ option: slots.option }} | ||||
|           v-slots={{ ...slots, option: slots.option }} | ||||
|         /> | ||||
|       ); | ||||
| 
 | ||||
|  | @ -1212,7 +1214,6 @@ export default function generateSelector< | |||
|         [`${prefixCls}-customize-input`]: customizeInputElement, | ||||
|         [`${prefixCls}-show-search`]: mergedShowSearch, | ||||
|       }); | ||||
| 
 | ||||
|       return ( | ||||
|         <div | ||||
|           {...this.$attrs} | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| import type { ExportedSelectProps } from './Select'; | ||||
| import Select from './Select'; | ||||
| import Select, { selectProps } from './Select'; | ||||
| import Option from './Option'; | ||||
| import OptGroup from './OptGroup'; | ||||
| import { selectBaseProps } from './generate'; | ||||
| import type { ExtractPropTypes } from 'vue'; | ||||
| 
 | ||||
| export type SelectProps<T = any> = Partial<ExtractPropTypes<ExportedSelectProps<T>>>; | ||||
| export { Option, OptGroup, selectBaseProps }; | ||||
| export { Option, OptGroup, selectBaseProps, selectProps }; | ||||
| 
 | ||||
| export default Select; | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ export const SelectContext = defineComponent({ | |||
|   }, | ||||
| }); | ||||
| 
 | ||||
| export const useInjectSelectContext = () => { | ||||
| export const useInjectTreeSelectContext = () => { | ||||
|   return inject( | ||||
|     SelectContextKey, | ||||
|     computed(() => ({} as ContextProps)), | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| import type { DataNode, TreeDataNode, Key } from './interface'; | ||||
| import { useInjectSelectContext } from './Context'; | ||||
| import { useInjectTreeSelectContext } from './Context'; | ||||
| import type { RefOptionListProps } from '../vc-select/OptionList'; | ||||
| import type { ScrollTo } from '../vc-virtual-list/List'; | ||||
| import { computed, defineComponent, nextTick, ref, watch } from 'vue'; | ||||
|  | @ -36,7 +36,7 @@ export default defineComponent({ | |||
|   slots: ['notFoundContent', 'menuItemSelectedIcon'], | ||||
|   expose: ['scrollTo', 'onKeydown', 'onKeyup'], | ||||
|   setup(props, { slots, expose }) { | ||||
|     const context = useInjectSelectContext(); | ||||
|     const context = useInjectTreeSelectContext(); | ||||
| 
 | ||||
|     const treeRef = ref(); | ||||
|     const memoOptions = useMemo( | ||||
|  | @ -144,7 +144,7 @@ export default defineComponent({ | |||
|       activeKey.value = key; | ||||
|     }; | ||||
|     expose({ | ||||
|       scrollTo: treeRef.value?.scrollTo as ScrollTo, | ||||
|       scrollTo: (...args: any[]) => treeRef.value.scrollTo?.(...args), | ||||
|       onKeydown: (event: KeyboardEvent) => { | ||||
|         const { which } = event; | ||||
|         switch (which) { | ||||
|  | @ -217,7 +217,6 @@ export default defineComponent({ | |||
|       if (mergedExpandedKeys.value) { | ||||
|         treeProps.expandedKeys = mergedExpandedKeys.value; | ||||
|       } | ||||
| 
 | ||||
|       return ( | ||||
|         <div onMousedown={onListMouseDown} onMouseenter={onMouseenter}> | ||||
|           {activeEntity.value && open && ( | ||||
|  | @ -255,7 +254,7 @@ export default defineComponent({ | |||
|             onExpand={onInternalExpand} | ||||
|             onLoad={onTreeLoad} | ||||
|             filterTreeNode={filterTreeNode} | ||||
|             v-slots={{ checkable: context.value.customCheckable }} | ||||
|             v-slots={{ ...slots, checkable: context.value.customCheckable }} | ||||
|           /> | ||||
|         </div> | ||||
|       ); | ||||
|  |  | |||
|  | @ -91,7 +91,15 @@ export default function generate(config: { | |||
|   return defineComponent({ | ||||
|     name: 'TreeSelect', | ||||
|     props: treeSelectProps(), | ||||
|     slots: ['placeholder', 'maxTagPlaceholder', 'treeIcon', 'switcherIcon', 'notFoundContent'], | ||||
|     slots: [ | ||||
|       'title', | ||||
|       'placeholder', | ||||
|       'maxTagPlaceholder', | ||||
|       'treeIcon', | ||||
|       'switcherIcon', | ||||
|       'notFoundContent', | ||||
|       'treeCheckable', | ||||
|     ], | ||||
|     TreeNode, | ||||
|     SHOW_ALL, | ||||
|     SHOW_PARENT, | ||||
|  | @ -105,7 +113,6 @@ export default function generate(config: { | |||
|       // ======================= Tree Data ======================= | ||||
|       // FieldNames | ||||
|       const mergedFieldNames = computed(() => fillFieldNames(props.fieldNames, true)); | ||||
| 
 | ||||
|       // Legacy both support `label` or `title` if not set. | ||||
|       // We have to fallback to function to handle this | ||||
|       const getTreeNodeTitle = (node: DataNode) => { | ||||
|  | @ -157,9 +164,9 @@ export default function generate(config: { | |||
|       const selectRef = ref(null); | ||||
| 
 | ||||
|       expose({ | ||||
|         scrollTo: selectRef.value.scrollTo, | ||||
|         focus: selectRef.value.focus, | ||||
|         blur: selectRef.value.blur, | ||||
|         scrollTo: (...args: any[]) => selectRef.value.scrollTo?.(...args), | ||||
|         focus: () => selectRef.value.focus?.(), | ||||
|         blur: () => selectRef.value?.blur(), | ||||
| 
 | ||||
|         /** @private Internal usage. It's save to remove if `rc-cascader` not use it any longer */ | ||||
|         getEntityByValue, | ||||
|  | @ -477,7 +484,7 @@ export default function generate(config: { | |||
|           treeNodeFilterProp, | ||||
|           getEntityByKey, | ||||
|           getEntityByValue, | ||||
|           customCheckable: slots.checkable, | ||||
|           customCheckable: slots.treeCheckable, | ||||
|           slots, | ||||
|         }; | ||||
|         return ( | ||||
|  | @ -496,6 +503,7 @@ export default function generate(config: { | |||
|               onSelect={null} | ||||
|               onDeselect={null} | ||||
|               onDropdownVisibleChange={onInternalDropdownVisibleChange} | ||||
|               v-slots={slots} | ||||
|             /> | ||||
|           </SelectContext> | ||||
|         ); | ||||
|  |  | |||
|  | @ -78,6 +78,10 @@ function formatTreeData( | |||
|         node, | ||||
|       }; | ||||
| 
 | ||||
|       if (node.slots) { | ||||
|         dataNode.slots = node.slots; | ||||
|       } | ||||
| 
 | ||||
|       // Check `key` & `value` and warning user
 | ||||
|       if (process.env.NODE_ENV !== 'production') { | ||||
|         if ( | ||||
|  |  | |||
|  | @ -38,6 +38,8 @@ export interface InternalDataEntity { | |||
| 
 | ||||
|   /** Origin DataNode */ | ||||
|   node: DataNode; | ||||
| 
 | ||||
|   slots?: Record<string, string>; // 兼容 V2
 | ||||
| } | ||||
| 
 | ||||
| export interface LegacyDataNode extends DataNode { | ||||
|  |  | |||
|  | @ -84,10 +84,6 @@ export default defineComponent({ | |||
|       // abstract-drag-over-node is the top node | ||||
|       dragOverNodeKey: null, | ||||
|     }); | ||||
|     warning( | ||||
|       !(props.treeData === undefined && props.children), | ||||
|       '`children` of Tree is deprecated. Please use `treeData` instead.', | ||||
|     ); | ||||
|     const treeData = computed(() => { | ||||
|       return props.treeData !== undefined ? props.treeData : convertTreeToData(props.children); | ||||
|     }); | ||||
|  | @ -953,6 +949,7 @@ export default defineComponent({ | |||
|     }; | ||||
|     expose({ | ||||
|       onNodeExpand, | ||||
|       scrollTo, | ||||
|     }); | ||||
|     onUnmounted(() => { | ||||
|       window.removeEventListener('dragend', onWindowDragEnd); | ||||
|  |  | |||
|  | @ -22,7 +22,9 @@ export default defineComponent({ | |||
|   setup(props, { attrs, slots, expose }) { | ||||
|     warning( | ||||
|       !('slots' in props.data), | ||||
|       'treeData slots is deprecated, please use `v-slot:icon` or `v-slot:title`, `v-slot:switcherIcon` instead', | ||||
|       `treeData slots is deprecated, please use ${Object.keys(props.data.slots || {}).map( | ||||
|         key => '`v-slot:' + key + '` ', | ||||
|       )}instead`, | ||||
|     ); | ||||
|     const dragNodeHighlight = ref(false); | ||||
|     const context = useInjectTreeContext(); | ||||
|  | @ -346,7 +348,9 @@ export default defineComponent({ | |||
|     // Icon + Title | ||||
|     const renderSelector = () => { | ||||
|       const { | ||||
|         title = slots.title || context.value.slots?.[props.data?.slots?.title], | ||||
|         title = slots.title || | ||||
|           context.value.slots?.[props.data?.slots?.title] || | ||||
|           context.value.slots?.title, | ||||
|         selected, | ||||
|         icon = slots.icon, | ||||
|         loading, | ||||
|  |  | |||
|  | @ -1,49 +1,63 @@ | |||
| <template> | ||||
|   <a-directory-tree | ||||
|     v-model:expandedKeys="expandedKeys" | ||||
|     v-model:selectedKeys="selectedKeys" | ||||
|     multiple | ||||
|     :tree-data1="treeData" | ||||
|   <a-tree-select | ||||
|     v-model:value="value" | ||||
|     style="width: 100%" | ||||
|     :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" | ||||
|     :tree-data="treeData" | ||||
|     placeholder="Please select" | ||||
|     tree-default-expand-all | ||||
|   > | ||||
|     <a-tree-node key="0-0" title="ddd" class="test" style="color: red"> | ||||
|       <template #title="{ title }">{{ title }}</template> | ||||
|       <a-tree-node key="0-0-0" title="leaf 0-0" is-leaf /> | ||||
|       <a-tree-node key="0-0-1" title="leaf 0-1" is-leaf /> | ||||
|     </a-tree-node> | ||||
|     <a-tree-node key="0-1" title="parent 1"> | ||||
|       <a-tree-node key="0-1-0" title="leaf 1-0" is-leaf /> | ||||
|       <a-tree-node key="0-1-1" title="leaf 1-1" is-leaf /> | ||||
|     </a-tree-node> | ||||
|   </a-directory-tree> | ||||
|     <template #title1="{ key, value }"> | ||||
|       <span v-if="key === '0-0-1'" style="color: #08c">Child Node1 {{ value }}</span> | ||||
|     </template> | ||||
|   </a-tree-select> | ||||
| </template> | ||||
| <script lang="ts"> | ||||
| import { defineComponent, ref, watch } from 'vue'; | ||||
| 
 | ||||
| interface TreeDataItem { | ||||
|   value: string; | ||||
|   key: string; | ||||
|   title?: string; | ||||
|   slots?: Record<string, string>; | ||||
|   children?: TreeDataItem[]; | ||||
| } | ||||
| 
 | ||||
| const treeData: TreeDataItem[] = [ | ||||
|   { | ||||
|     title: 'Node1', | ||||
|     value: '0-0', | ||||
|     key: '0-0', | ||||
|     children: [ | ||||
|       { | ||||
|         value: '0-0-1', | ||||
|         key: '0-0-1', | ||||
|         slots: { | ||||
|           title: 'title1', | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|         title: 'Child Node2', | ||||
|         value: '0-0-2', | ||||
|         key: '0-0-2', | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
|   { | ||||
|     title: 'Node2', | ||||
|     value: '0-1', | ||||
|     key: '0-1', | ||||
|   }, | ||||
| ]; | ||||
| export default defineComponent({ | ||||
|   setup() { | ||||
|     const expandedKeys = ref<string[]>([]); | ||||
|     const selectedKeys = ref<string[]>([]); | ||||
|     const treeData = [ | ||||
|       { | ||||
|         title: 'parent 0', | ||||
|         key: '0-0', | ||||
|         children: [ | ||||
|           { title: 'leaf 0-0', key: '0-0-0', isLeaf: true }, | ||||
|           // { title: 'leaf 0-1', key: '0-0-1', isLeaf: true }, | ||||
|         ], | ||||
|       }, | ||||
|       { | ||||
|         title: 'parent 1', | ||||
|         key: '0-1', | ||||
|         children: [ | ||||
|           { title: 'leaf 1-0', key: '0-1-0', isLeaf: true }, | ||||
|           { title: 'leaf 1-1', key: '0-1-1', isLeaf: true }, | ||||
|         ], | ||||
|       }, | ||||
|     ]; | ||||
|     const value = ref<string>(); | ||||
| 
 | ||||
|     watch(value, () => { | ||||
|       console.log(value.value); | ||||
|     }); | ||||
|     return { | ||||
|       expandedKeys, | ||||
|       selectedKeys, | ||||
|       onTest: () => {}, | ||||
|       value, | ||||
|       treeData, | ||||
|     }; | ||||
|   }, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou