mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[new feature] TreeSelect: add content slot (#4105)
This commit is contained in:
parent
6413cd1996
commit
317b115da8
@ -63,6 +63,12 @@ export default {
|
|||||||
| click-nav | triggered when parent node is selected | index: index of selected parent |
|
| click-nav | triggered when parent node is selected | index: index of selected parent |
|
||||||
| click-item | triggered when item is selected | data: selected item |
|
| click-item | triggered when item is selected | data: selected item |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
|------|------|
|
||||||
|
| content | Custom right content |
|
||||||
|
|
||||||
### Data Structure of Item
|
### Data Structure of Item
|
||||||
|
|
||||||
`items` should be an array contains specified tree objects.
|
`items` should be an array contains specified tree objects.
|
||||||
|
@ -63,6 +63,12 @@ export default {
|
|||||||
| click-nav | 点击左侧导航时触发 | index:被点击的导航的索引 |
|
| click-nav | 点击左侧导航时触发 | index:被点击的导航的索引 |
|
||||||
| click-item | 点击右侧选择项时触发 | data: 该点击项的数据 |
|
| click-item | 点击右侧选择项时触发 | data: 该点击项的数据 |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| content | 自定义右侧区域内容 |
|
||||||
|
|
||||||
### Item 数据结构
|
### Item 数据结构
|
||||||
|
|
||||||
`items` 整体为一个数组,数组内包含一系列描述分类的对象。
|
`items` 整体为一个数组,数组内包含一系列描述分类的对象。
|
||||||
|
@ -4,7 +4,7 @@ import Icon from '../icon';
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { CreateElement, RenderContext } from 'vue/types';
|
import { CreateElement, RenderContext } from 'vue/types';
|
||||||
import { DefaultSlots } from '../utils/types';
|
import { DefaultSlots, ScopedSlot } from '../utils/types';
|
||||||
|
|
||||||
export type TreeSelectItem = {
|
export type TreeSelectItem = {
|
||||||
text: string;
|
text: string;
|
||||||
@ -25,12 +25,16 @@ export type TreeSelectProps = {
|
|||||||
mainActiveIndex: number;
|
mainActiveIndex: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TreeSelectSlots = DefaultSlots & {
|
||||||
|
content?: ScopedSlot;
|
||||||
|
};
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('tree-select');
|
const [createComponent, bem] = createNamespace('tree-select');
|
||||||
|
|
||||||
function TreeSelect(
|
function TreeSelect(
|
||||||
h: CreateElement,
|
h: CreateElement,
|
||||||
props: TreeSelectProps,
|
props: TreeSelectProps,
|
||||||
slots: DefaultSlots,
|
slots: TreeSelectSlots,
|
||||||
ctx: RenderContext<TreeSelectProps>
|
ctx: RenderContext<TreeSelectProps>
|
||||||
) {
|
) {
|
||||||
const { height, items, mainActiveIndex, activeId } = props;
|
const { height, items, mainActiveIndex, activeId } = props;
|
||||||
@ -38,10 +42,7 @@ function TreeSelect(
|
|||||||
const selectedItem: Partial<TreeSelectItem> = items[mainActiveIndex] || {};
|
const selectedItem: Partial<TreeSelectItem> = items[mainActiveIndex] || {};
|
||||||
const subItems = selectedItem.children || [];
|
const subItems = selectedItem.children || [];
|
||||||
|
|
||||||
return (
|
const Nav = items.map((item, index) => (
|
||||||
<div class={bem()} style={{ height: `${height}px` }} {...inherit(ctx)}>
|
|
||||||
<div class={bem('nav')}>
|
|
||||||
{items.map((item, index) => (
|
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
class={[
|
class={[
|
||||||
@ -62,10 +63,14 @@ function TreeSelect(
|
|||||||
>
|
>
|
||||||
{item.text}
|
{item.text}
|
||||||
</div>
|
</div>
|
||||||
))}
|
));
|
||||||
</div>
|
|
||||||
<div class={bem('content')}>
|
function Content() {
|
||||||
{subItems.map(item => (
|
if (slots.content) {
|
||||||
|
return slots.content();
|
||||||
|
}
|
||||||
|
|
||||||
|
return subItems.map(item => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
class={[
|
class={[
|
||||||
@ -89,8 +94,13 @@ function TreeSelect(
|
|||||||
<Icon name="checked" size="16px" class={bem('selected')} />
|
<Icon name="checked" size="16px" class={bem('selected')} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
));
|
||||||
</div>
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={bem()} style={{ height: `${height}px` }} {...inherit(ctx)}>
|
||||||
|
<div class={bem('nav')}>{Nav}</div>
|
||||||
|
<div class={bem('content')}>{Content()}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`content slot 1`] = `
|
||||||
|
<div class="van-tree-select" style="height: 300px;">
|
||||||
|
<div class="van-tree-select__nav">
|
||||||
|
<div class="van-ellipsis van-tree-select__nav-item van-tree-select__nav-item--active">group1</div>
|
||||||
|
</div>
|
||||||
|
<div class="van-tree-select__content">Custom Content</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`empty list 1`] = `
|
exports[`empty list 1`] = `
|
||||||
<div class="van-tree-select" style="height: 300px;">
|
<div class="van-tree-select" style="height: 300px;">
|
||||||
<div class="van-tree-select__nav"></div>
|
<div class="van-tree-select__nav"></div>
|
||||||
|
@ -124,3 +124,20 @@ test('click disabled item', () => {
|
|||||||
items.at(0).trigger('click');
|
items.at(0).trigger('click');
|
||||||
expect(onClickItem).toHaveBeenCalledTimes(0);
|
expect(onClickItem).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('content slot', () => {
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
scopedSlots: {
|
||||||
|
content: () => 'Custom Content'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user