refactor: tree-select
parent
1581943eb0
commit
76ee4d6856
|
@ -17,7 +17,13 @@ const initDefaultProps = <T>(
|
|||
Object.keys(defaultProps).forEach(k => {
|
||||
const prop = propTypes[k] as VueTypeValidableDef;
|
||||
if (prop) {
|
||||
if (prop.type || prop.default) {
|
||||
prop.default = defaultProps[k];
|
||||
} else if (prop.def) {
|
||||
prop.def(defaultProps[k]);
|
||||
} else {
|
||||
propTypes[k] = { type: prop, default: defaultProps[k] };
|
||||
}
|
||||
} else {
|
||||
throw new Error(`not have ${k} prop`);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ import VcTreeSelect, {
|
|||
import classNames from '../_util/classNames';
|
||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||
import type { SizeType } from '../config-provider';
|
||||
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';
|
||||
import omit from '../_util/omit';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
|
@ -237,78 +235,6 @@ const TreeSelect = defineComponent({
|
|||
);
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveTreeSelect(node: any) {
|
||||
this.vcTreeSelect = node;
|
||||
},
|
||||
focus() {
|
||||
this.vcTreeSelect.focus();
|
||||
},
|
||||
|
||||
blur() {
|
||||
this.vcTreeSelect.blur();
|
||||
},
|
||||
renderSwitcherIcon(prefixCls: string, { isLeaf, loading }) {
|
||||
if (loading) {
|
||||
return <LoadingOutlined class={`${prefixCls}-switcher-loading-icon`} />;
|
||||
}
|
||||
if (isLeaf) {
|
||||
return null;
|
||||
}
|
||||
return <CaretDownOutlined class={`${prefixCls}-switcher-icon`} />;
|
||||
},
|
||||
handleChange(...args: any[]) {
|
||||
this.$emit('update:value', args[0]);
|
||||
this.$emit('change', ...args);
|
||||
},
|
||||
handleTreeExpand(...args: any[]) {
|
||||
this.$emit('update:treeExpandedKeys', args[0]);
|
||||
this.$emit('treeExpand', ...args);
|
||||
},
|
||||
handleSearch(...args: any[]) {
|
||||
this.$emit('update:searchValue', args[0]);
|
||||
this.$emit('search', ...args);
|
||||
},
|
||||
updateTreeData(treeData: any[]) {
|
||||
const { $slots } = this;
|
||||
const defaultFields = {
|
||||
children: 'children',
|
||||
title: 'title',
|
||||
key: 'key',
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
};
|
||||
const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
|
||||
return treeData.map(item => {
|
||||
const { slots = {} } = item;
|
||||
const label = item[replaceFields.label];
|
||||
const title = item[replaceFields.title];
|
||||
const value = item[replaceFields.value];
|
||||
const key = item[replaceFields.key];
|
||||
const children = item[replaceFields.children];
|
||||
let newLabel = typeof label === 'function' ? label() : label;
|
||||
let newTitle = typeof title === 'function' ? title() : title;
|
||||
if (!newLabel && slots.label && $slots[slots.label]) {
|
||||
newLabel = <>{$slots[slots.label](item)}</>;
|
||||
}
|
||||
if (!newTitle && slots.title && $slots[slots.title]) {
|
||||
newTitle = <>{$slots[slots.title](item)}</>;
|
||||
}
|
||||
const treeNodeProps = {
|
||||
...item,
|
||||
title: newTitle || newLabel,
|
||||
value,
|
||||
dataRef: item,
|
||||
key,
|
||||
};
|
||||
if (children) {
|
||||
return { ...treeNodeProps, children: this.updateTreeData(children) };
|
||||
}
|
||||
return treeNodeProps;
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
|
|
|
@ -8,6 +8,7 @@ import PropTypes from '../_util/vue-types';
|
|||
import { filterEmpty } from '../_util/props-util';
|
||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||
import type { DataNode, DragNodeEvent, FieldNames, Key } from '../vc-tree/interface';
|
||||
import type { TreeNodeProps } from '../vc-tree/props';
|
||||
import { treeProps as vcTreeProps } from '../vc-tree/props';
|
||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||
import renderSwitcherIcon from './utils/iconUtil';
|
||||
|
@ -35,7 +36,7 @@ export interface AntdTreeNodeAttribute {
|
|||
disableCheckbox: boolean;
|
||||
}
|
||||
|
||||
export type AntTreeNodeProps = DataNode;
|
||||
export type AntTreeNodeProps = TreeNodeProps;
|
||||
|
||||
// [Legacy] Compatible for v2
|
||||
export type TreeDataItem = DataNode;
|
||||
|
|
|
@ -11,7 +11,6 @@ export {
|
|||
AntTreeNodeCheckedEvent,
|
||||
AntTreeNodeSelectedEvent,
|
||||
AntdTreeNodeAttribute,
|
||||
AntTreeNodeProps,
|
||||
TreeDataItem,
|
||||
} from './Tree';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { DataNode, Key } from 'ant-design-vue/es/vc-tree/interface';
|
||||
import type { DataNode, Key } from '../../vc-tree/interface';
|
||||
|
||||
enum Record {
|
||||
None,
|
||||
|
|
|
@ -4,7 +4,7 @@ import MinusSquareOutlined from '@ant-design/icons-vue/MinusSquareOutlined';
|
|||
import PlusSquareOutlined from '@ant-design/icons-vue/PlusSquareOutlined';
|
||||
import CaretDownFilled from '@ant-design/icons-vue/CaretDownFilled';
|
||||
import type { AntTreeNodeProps } from '../Tree';
|
||||
import { isValidElement } from 'ant-design-vue/es/_util/props-util';
|
||||
import { isValidElement } from '../../_util/props-util';
|
||||
|
||||
import { cloneVNode } from 'vue';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import type { VNodeChild } from 'vue';
|
|||
import { Fragment } 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';
|
||||
import { useInjectTreeSelectContext } from '../../vc-tree-select/Context';
|
||||
|
||||
interface SelectorProps extends InnerSelectorProps {
|
||||
inputElement: VNodeChild;
|
||||
|
|
|
@ -1034,7 +1034,7 @@ export default function generateSelector<
|
|||
internalProps = {},
|
||||
|
||||
...restProps
|
||||
} = props; //as SelectProps<OptionType[], ValueType>;
|
||||
} = { ...props, ...attrs }; //as SelectProps<OptionType[], ValueType>;
|
||||
// ============================= Input ==============================
|
||||
// Only works in `combobox`
|
||||
const customizeInputElement: VNodeChild | JSX.Element =
|
||||
|
@ -1144,9 +1144,8 @@ export default function generateSelector<
|
|||
});
|
||||
return (
|
||||
<div
|
||||
{...attrs}
|
||||
class={mergedClassName}
|
||||
{...domProps}
|
||||
class={mergedClassName}
|
||||
ref={containerRef}
|
||||
onMousedown={onInternalMouseDown}
|
||||
onKeydown={onInternalKeyDown}
|
||||
|
|
|
@ -143,7 +143,7 @@ export default defineComponent({
|
|||
activeKey.value = key;
|
||||
};
|
||||
expose({
|
||||
scrollTo: (...args: any[]) => treeRef.value.scrollTo?.(...args),
|
||||
scrollTo: (...args: any[]) => treeRef.value?.scrollTo?.(...args),
|
||||
onKeydown: (event: KeyboardEvent) => {
|
||||
const { which } = event;
|
||||
switch (which) {
|
||||
|
|
|
@ -64,6 +64,7 @@ const OMIT_PROPS: (keyof TreeSelectProps)[] = [
|
|||
'treeDataSimpleMode',
|
||||
'treeNodeLabelProp',
|
||||
'treeDefaultExpandedKeys',
|
||||
'bordered',
|
||||
];
|
||||
|
||||
export default function generate(config: {
|
||||
|
@ -236,8 +237,9 @@ export default function generate(config: {
|
|||
...checkedKeys.map(key => getEntityByKey(key).data.value),
|
||||
];
|
||||
rawHalfCheckedKeys.value = halfCheckedKeys;
|
||||
}
|
||||
} else {
|
||||
[rawValues.value, rawHalfCheckedKeys.value] = [newRawValues, valueHalfCheckedKeys];
|
||||
}
|
||||
});
|
||||
|
||||
const selectValues = useSelectValues(rawValues, {
|
||||
|
@ -378,7 +380,7 @@ export default function generate(config: {
|
|||
option: DataNode,
|
||||
source: SelectSource,
|
||||
) => {
|
||||
const eventValue = mergedLabelInValue.value ? selectValue : selectValue;
|
||||
const eventValue = selectValue;
|
||||
|
||||
let newRawValues = removeValue(rawValues.value, selectValue);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { warning } from 'ant-design-vue/es/vc-util/warning';
|
||||
import { warning } from '../../vc-util/warning';
|
||||
import type { ComputedRef, Ref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import type {
|
||||
|
@ -76,6 +76,7 @@ function formatTreeData(
|
|||
value: mergedValue,
|
||||
title: getLabelProp(node),
|
||||
node,
|
||||
dataRef: node,
|
||||
};
|
||||
|
||||
if (node.slots) {
|
||||
|
|
|
@ -39,6 +39,8 @@ export interface InternalDataEntity {
|
|||
/** Origin DataNode */
|
||||
node: DataNode;
|
||||
|
||||
dataRef: DataNode;
|
||||
|
||||
slots?: Record<string, string>; // 兼容 V2
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ import type {
|
|||
} from '../interface';
|
||||
import { fillLegacyProps } from './legacyUtil';
|
||||
import type { SkipType } from '../hooks/useKeyValueMapping';
|
||||
import type { FlattenNode } from 'ant-design-vue/es/vc-tree/interface';
|
||||
import { flattenTreeData } from 'ant-design-vue/es/vc-tree/utils/treeUtil';
|
||||
import type { FilterFunc } from 'ant-design-vue/es/vc-select/interface/generator';
|
||||
import type { FlattenNode } from '../../vc-tree/interface';
|
||||
import { flattenTreeData } from '../../vc-tree/utils/treeUtil';
|
||||
import type { FilterFunc } from '../../vc-select/interface/generator';
|
||||
|
||||
type CompatibleDataNode = Omit<FlattenDataNode, 'level'>;
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { warning } from '../../vc-util/warning';
|
||||
import type { TreeSelectProps } from '../TreeSelect';
|
||||
import { toArray } from './valueUtil';
|
||||
|
||||
function warningProps(props: TreeSelectProps) {
|
||||
function warningProps(props: any) {
|
||||
const { searchPlaceholder, treeCheckStrictly, treeCheckable, labelInValue, value, multiple } =
|
||||
props;
|
||||
|
||||
warning(!searchPlaceholder, '`searchPlaceholder` has been removed.');
|
||||
warning(
|
||||
!searchPlaceholder,
|
||||
'`searchPlaceholder` has been removed, please use `placeholder` instead',
|
||||
);
|
||||
|
||||
if (treeCheckStrictly && labelInValue === false) {
|
||||
warning(false, '`treeCheckStrictly` will force set `labelInValue` to `true`.');
|
||||
|
|
|
@ -634,7 +634,7 @@ export default defineComponent({
|
|||
|
||||
checkedObj = newCheckedKeys;
|
||||
|
||||
// [Legacy] This is used for `rc-tree-select`
|
||||
// [Legacy] This is used for vc-tree-select`
|
||||
eventObj.checkedNodes = [];
|
||||
eventObj.checkedNodesPositions = [];
|
||||
eventObj.halfCheckedKeys = newHalfCheckedKeys;
|
||||
|
@ -997,7 +997,6 @@ export default defineComponent({
|
|||
|
||||
const { class: className, style } = attrs;
|
||||
const domProps = getDataAndAria({ ...props, ...attrs });
|
||||
|
||||
return (
|
||||
<TreeContext
|
||||
value={{
|
||||
|
|
|
@ -402,8 +402,8 @@ export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode
|
|||
pos,
|
||||
active,
|
||||
} = props;
|
||||
|
||||
const eventData = {
|
||||
dataRef: data,
|
||||
...data,
|
||||
expanded,
|
||||
selected,
|
||||
|
@ -416,7 +416,6 @@ export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode
|
|||
dragOverGapBottom,
|
||||
pos,
|
||||
active,
|
||||
dataRef: data,
|
||||
eventKey: data.key,
|
||||
};
|
||||
if (!('props' in eventData)) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-tree-select
|
||||
v-model:value="value"
|
||||
show-search
|
||||
|
@ -6,35 +7,74 @@
|
|||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
placeholder="Please select"
|
||||
allow-clear
|
||||
multiple
|
||||
tree-default-expand-all
|
||||
:tree-data="treeData"
|
||||
>
|
||||
<a-tree-select-node value="parent 1" title="parent 1">
|
||||
<a-tree-select-node value="parent 1-0" title="parent 1-0">
|
||||
<a-tree-select-node value="leaf1" title="my leaf" />
|
||||
<a-tree-select-node value="leaf2" title="your leaf" />
|
||||
</a-tree-select-node>
|
||||
<a-tree-select-node value="parent 1-1" title="parent 1-1">
|
||||
<a-tree-select-node value="sss">
|
||||
<template #title><b style="color: #08c">sss</b></template>
|
||||
</a-tree-select-node>
|
||||
</a-tree-select-node>
|
||||
</a-tree-select-node>
|
||||
<template #suffixIcon><SmileOutlined /></template>
|
||||
</a-tree-select>
|
||||
|
||||
<a-tree-select
|
||||
v-model:value="value1"
|
||||
show-search
|
||||
style="width: 100%"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
placeholder="Please select"
|
||||
allow-clear
|
||||
multiple
|
||||
show-arrow
|
||||
tree-default-expand-all
|
||||
:tree-data="treeData"
|
||||
>
|
||||
<template #suffixIcon><SmileOutlined /></template>
|
||||
</a-tree-select>
|
||||
</a-space>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { SmileOutlined } from '@ant-design/icons-vue';
|
||||
import { TreeSelectProps } from 'ant-design-vue';
|
||||
import { defineComponent, ref, watch } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SmileOutlined,
|
||||
},
|
||||
setup() {
|
||||
const value = ref<string[]>([]);
|
||||
|
||||
const value1 = ref<string[]>([]);
|
||||
const treeData = ref<TreeSelectProps['treeData']>([
|
||||
{
|
||||
title: 'parent 1',
|
||||
value: 'parent 1',
|
||||
children: [
|
||||
{
|
||||
title: 'parent 1-0',
|
||||
value: 'parent 1-0',
|
||||
children: [
|
||||
{
|
||||
title: 'my leaf',
|
||||
value: 'leaf1',
|
||||
},
|
||||
{
|
||||
title: 'your leaf',
|
||||
value: 'leaf2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-1',
|
||||
value: 'parent 1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
watch(value, () => {
|
||||
console.log('select', value.value);
|
||||
});
|
||||
|
||||
return {
|
||||
value,
|
||||
value1,
|
||||
treeData,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
2
v2-doc
2
v2-doc
|
@ -1 +1 @@
|
|||
Subproject commit 2e39bc81a84e2cfa90e8863e8f18d5a3d3ab1995
|
||||
Subproject commit 3f94a02d16bac2377d71e26948ffe45571dae49e
|
Loading…
Reference in New Issue