mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
types(Cascader): add CascaderProps type (#9684)
This commit is contained in:
parent
843fd4f2a3
commit
ab1543cf3a
@ -1,4 +1,11 @@
|
|||||||
import { nextTick, PropType, reactive, watch, defineComponent } from 'vue';
|
import {
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
PropType,
|
||||||
|
defineComponent,
|
||||||
|
ExtractPropTypes,
|
||||||
|
} from 'vue';
|
||||||
import {
|
import {
|
||||||
extend,
|
extend,
|
||||||
truthProp,
|
truthProp,
|
||||||
@ -15,53 +22,34 @@ import { Icon } from '../icon';
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
import type { TabsClickTabEventParams } from '../tabs/types';
|
import type { TabsClickTabEventParams } from '../tabs/types';
|
||||||
|
import type { CascaderTab, CascaderOption, CascaderFieldNames } from './types';
|
||||||
|
|
||||||
const [name, bem, t] = createNamespace('cascader');
|
const [name, bem, t] = createNamespace('cascader');
|
||||||
|
|
||||||
export type CascaderOption = {
|
const props = {
|
||||||
text?: string;
|
title: String,
|
||||||
value?: string | number;
|
options: makeArrayProp<CascaderOption>(),
|
||||||
color?: string;
|
closeable: truthProp,
|
||||||
disabled?: boolean;
|
swipeable: truthProp,
|
||||||
children?: CascaderOption[];
|
closeIcon: makeStringProp('cross'),
|
||||||
className?: unknown;
|
modelValue: numericProp,
|
||||||
// for custom filed names
|
fieldNames: Object as PropType<CascaderFieldNames>,
|
||||||
[key: PropertyKey]: any;
|
placeholder: String,
|
||||||
|
activeColor: String,
|
||||||
};
|
};
|
||||||
|
|
||||||
type CascaderTab = {
|
export type CascaderProps = ExtractPropTypes<typeof props>;
|
||||||
options: CascaderOption[];
|
|
||||||
selected: CascaderOption | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CascaderFieldNames = {
|
|
||||||
text?: string;
|
|
||||||
value?: string;
|
|
||||||
children?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name,
|
name,
|
||||||
|
|
||||||
props: {
|
props,
|
||||||
title: String,
|
|
||||||
options: makeArrayProp<CascaderOption>(),
|
|
||||||
closeable: truthProp,
|
|
||||||
swipeable: truthProp,
|
|
||||||
closeIcon: makeStringProp('cross'),
|
|
||||||
modelValue: numericProp,
|
|
||||||
fieldNames: Object as PropType<CascaderFieldNames>,
|
|
||||||
placeholder: String,
|
|
||||||
activeColor: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['close', 'change', 'finish', 'update:modelValue', 'click-tab'],
|
emits: ['close', 'change', 'finish', 'click-tab', 'update:modelValue'],
|
||||||
|
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const state = reactive({
|
const tabs = ref<CascaderTab[]>([]);
|
||||||
tabs: [] as CascaderTab[],
|
const activeTab = ref(0);
|
||||||
activeTab: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
text: textKey,
|
text: textKey,
|
||||||
@ -98,16 +86,15 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateTabs = () => {
|
const updateTabs = () => {
|
||||||
if (props.modelValue || props.modelValue === 0) {
|
const { options, modelValue } = props;
|
||||||
const selectedOptions = getSelectedOptionsByValue(
|
|
||||||
props.options,
|
if (modelValue !== undefined) {
|
||||||
props.modelValue
|
const selectedOptions = getSelectedOptionsByValue(options, modelValue);
|
||||||
);
|
|
||||||
|
|
||||||
if (selectedOptions) {
|
if (selectedOptions) {
|
||||||
let optionsCursor = props.options;
|
let optionsCursor = options;
|
||||||
|
|
||||||
state.tabs = selectedOptions.map((option) => {
|
tabs.value = selectedOptions.map((option) => {
|
||||||
const tab = {
|
const tab = {
|
||||||
options: optionsCursor,
|
options: optionsCursor,
|
||||||
selected: option,
|
selected: option,
|
||||||
@ -124,23 +111,23 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (optionsCursor) {
|
if (optionsCursor) {
|
||||||
state.tabs.push({
|
tabs.value.push({
|
||||||
options: optionsCursor,
|
options: optionsCursor,
|
||||||
selected: null,
|
selected: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
state.activeTab = state.tabs.length - 1;
|
activeTab.value = tabs.value.length - 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.tabs = [
|
tabs.value = [
|
||||||
{
|
{
|
||||||
options: props.options,
|
options,
|
||||||
selected: null,
|
selected: null,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -151,10 +138,10 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.tabs[tabIndex].selected = option;
|
tabs.value[tabIndex].selected = option;
|
||||||
|
|
||||||
if (state.tabs.length > tabIndex + 1) {
|
if (tabs.value.length > tabIndex + 1) {
|
||||||
state.tabs = state.tabs.slice(0, tabIndex + 1);
|
tabs.value = tabs.value.slice(0, tabIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option[childrenKey]) {
|
if (option[childrenKey]) {
|
||||||
@ -163,31 +150,32 @@ export default defineComponent({
|
|||||||
selected: null,
|
selected: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (state.tabs[tabIndex + 1]) {
|
if (tabs.value[tabIndex + 1]) {
|
||||||
state.tabs[tabIndex + 1] = nextTab;
|
tabs.value[tabIndex + 1] = nextTab;
|
||||||
} else {
|
} else {
|
||||||
state.tabs.push(nextTab);
|
tabs.value.push(nextTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
state.activeTab++;
|
activeTab.value++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedOptions = state.tabs
|
const selectedOptions = tabs.value
|
||||||
.map((tab) => tab.selected)
|
.map((tab) => tab.selected)
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
const eventParams = {
|
emit('update:modelValue', option[valueKey]);
|
||||||
|
|
||||||
|
const params = {
|
||||||
value: option[valueKey],
|
value: option[valueKey],
|
||||||
tabIndex,
|
tabIndex,
|
||||||
selectedOptions,
|
selectedOptions,
|
||||||
};
|
};
|
||||||
emit('update:modelValue', option[valueKey]);
|
emit('change', params);
|
||||||
emit('change', eventParams);
|
|
||||||
|
|
||||||
if (!option[childrenKey]) {
|
if (!option[childrenKey]) {
|
||||||
emit('finish', eventParams);
|
emit('finish', params);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -260,9 +248,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
const renderTab = (tab: CascaderTab, tabIndex: number) => {
|
const renderTab = (tab: CascaderTab, tabIndex: number) => {
|
||||||
const { options, selected } = tab;
|
const { options, selected } = tab;
|
||||||
const title = selected
|
const placeholder = props.placeholder || t('select');
|
||||||
? selected[textKey]
|
const title = selected ? selected[textKey] : placeholder;
|
||||||
: props.placeholder || t('select');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab
|
<Tab
|
||||||
@ -278,7 +265,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
const renderTabs = () => (
|
const renderTabs = () => (
|
||||||
<Tabs
|
<Tabs
|
||||||
v-model:active={state.activeTab}
|
v-model:active={activeTab.value}
|
||||||
animated
|
animated
|
||||||
class={bem('tabs')}
|
class={bem('tabs')}
|
||||||
color={props.activeColor}
|
color={props.activeColor}
|
||||||
@ -286,7 +273,7 @@ export default defineComponent({
|
|||||||
swipeable={props.swipeable}
|
swipeable={props.swipeable}
|
||||||
onClick-tab={onClickTab}
|
onClick-tab={onClickTab}
|
||||||
>
|
>
|
||||||
{state.tabs.map(renderTab)}
|
{tabs.value.map(renderTab)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -296,8 +283,8 @@ export default defineComponent({
|
|||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value || value === 0) {
|
if (value !== undefined) {
|
||||||
const values = state.tabs.map((tab) => tab.selected?.[valueKey]);
|
const values = tabs.value.map((tab) => tab.selected?.[valueKey]);
|
||||||
if (values.includes(value)) {
|
if (values.includes(value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ export default {
|
|||||||
The component exports the following type definitions:
|
The component exports the following type definitions:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CascaderOption, CascaderFieldNames } from 'vant';
|
import type { CascaderProps, CascaderOption, CascaderFieldNames } from 'vant';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Theming
|
## Theming
|
||||||
|
@ -257,7 +257,7 @@ export default {
|
|||||||
组件导出以下类型定义:
|
组件导出以下类型定义:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import type { CascaderOption, CascaderFieldNames } from 'vant';
|
import type { CascaderProps, CascaderOption, CascaderFieldNames } from 'vant';
|
||||||
```
|
```
|
||||||
|
|
||||||
## 主题定制
|
## 主题定制
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { withInstall } from '../utils';
|
import { withInstall } from '../utils';
|
||||||
import _Cascader from './Cascader';
|
import _Cascader, { CascaderProps } from './Cascader';
|
||||||
|
|
||||||
export const Cascader = withInstall(_Cascader);
|
export const Cascader = withInstall(_Cascader);
|
||||||
export default Cascader;
|
export default Cascader;
|
||||||
export type { CascaderOption, CascaderFieldNames } from './Cascader';
|
export type { CascaderProps };
|
||||||
|
export type { CascaderOption, CascaderFieldNames } from './types';
|
||||||
|
21
packages/vant/src/cascader/types.ts
Normal file
21
packages/vant/src/cascader/types.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export type CascaderOption = {
|
||||||
|
text?: string;
|
||||||
|
value?: string | number;
|
||||||
|
color?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
children?: CascaderOption[];
|
||||||
|
className?: unknown;
|
||||||
|
// for custom filed names
|
||||||
|
[key: PropertyKey]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CascaderTab = {
|
||||||
|
options: CascaderOption[];
|
||||||
|
selected: CascaderOption | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CascaderFieldNames = {
|
||||||
|
text?: string;
|
||||||
|
value?: string;
|
||||||
|
children?: string;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user