parent
aa1bcfe5db
commit
804a1eba18
@ -0,0 +1,30 @@
|
|||||||
|
<cn>
|
||||||
|
#### 基本
|
||||||
|
最简单的下拉菜单。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Basic
|
||||||
|
The most basic dropdown menu.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item>
|
||||||
|
<a href="javascript:;">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a href="javascript:;">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a href="javascript:;">3rd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
@ -0,0 +1,22 @@
|
|||||||
|
<cn>
|
||||||
|
#### 右键菜单
|
||||||
|
默认是移入触发菜单,可以鼠标右键触发。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Context Menu
|
||||||
|
The default trigger mode is `hover`, you can change it to `right click`.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown :trigger="['contextmenu']">
|
||||||
|
<span style="user-select: none">Right Click on Me</span>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd menu item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
@ -0,0 +1,59 @@
|
|||||||
|
<cn>
|
||||||
|
#### 带下拉框的按钮
|
||||||
|
左边是按钮,右边是额外的相关功能菜单。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Button with dropdown menu
|
||||||
|
A button is on the left, and a related functional menu is on the right.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-dropdown-button @click="handleMenuClick">
|
||||||
|
Dropdown
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown-button>
|
||||||
|
<a-dropdown-button
|
||||||
|
@click="handleButtonClick"
|
||||||
|
disabled
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
Dropdown
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown-button>
|
||||||
|
<a-dropdown>
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
<a-button style="margin-left: 8px">
|
||||||
|
Button <a-icon type="down" />
|
||||||
|
</a-button>
|
||||||
|
</a-dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleButtonClick(e) {
|
||||||
|
console.log('click left button', e);
|
||||||
|
},
|
||||||
|
handleMenuClick(e) {
|
||||||
|
console.log('click', e);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
@ -0,0 +1,34 @@
|
|||||||
|
<cn>
|
||||||
|
#### 触发事件
|
||||||
|
点击菜单项后会触发事件,用户可以通过相应的菜单项 key 进行不同的操作。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Click event
|
||||||
|
An event will be triggered when you click menu items, in which you can make different operations according to item's key.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me, Click menu item <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay" @click="onClick">
|
||||||
|
<a-menu-item key="1">1st menu item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd menu item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd menu item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
onClick({ key }) {
|
||||||
|
console.log(`Click on item ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
@ -0,0 +1,41 @@
|
|||||||
|
<cn>
|
||||||
|
#### 菜单隐藏方式
|
||||||
|
默认是点击关闭菜单,可以关闭此功能。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### The way of hiding menu.
|
||||||
|
The default is to close the menu when you click on menu items, this feature can be turned off.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown v-model="visible">
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Hover me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay" @click="handleMenuClick">
|
||||||
|
<a-menu-item key="1">Clicking me will not close the menu.</a-menu-item>
|
||||||
|
<a-menu-item key="2">Clicking me will not close the menu also.</a-menu-item>
|
||||||
|
<a-menu-item key="3">Clicking me will close the menu</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleMenuClick (e) {
|
||||||
|
if (e.key === '3') {
|
||||||
|
this.visible = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
@ -0,0 +1,49 @@
|
|||||||
|
<cn>
|
||||||
|
#### 弹出位置
|
||||||
|
支持 6 个弹出位置。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Placement
|
||||||
|
Support 6 placements.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div id="components-dropdown-demo-placement">
|
||||||
|
<template v-for="(placement, index) in placements">
|
||||||
|
<a-dropdown :placement="placement">
|
||||||
|
<a-button>{{placement}}</a-button>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">3rd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
<br v-if="index === 2"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
placements: ['bottomLeft', 'bottomCenter', 'bottomRight', 'topLeft', 'topCenter', 'topRight'],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
#components-dropdown-demo-placement .ant-btn {
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
@ -0,0 +1,31 @@
|
|||||||
|
<cn>
|
||||||
|
#### 多级菜单
|
||||||
|
传入的菜单里有多个层级。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Cascading menu
|
||||||
|
The menu has multiple levels.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown>
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Cascading menu <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item>1st menu item</a-menu-item>
|
||||||
|
<a-menu-item>2nd menu item</a-menu-item>
|
||||||
|
<a-sub-menu title="sub menu" key="test">
|
||||||
|
<a-menu-item>3rd menu item</a-menu-item>
|
||||||
|
<a-menu-item>4th menu item</a-menu-item>
|
||||||
|
</a-sub-menu>
|
||||||
|
<a-sub-menu title="disabled sub menu" disabled>
|
||||||
|
<a-menu-item>5d menu item</a-menu-item>
|
||||||
|
<a-menu-item>6th menu item</a-menu-item>
|
||||||
|
</a-sub-menu>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
@ -0,0 +1,29 @@
|
|||||||
|
<cn>
|
||||||
|
#### 触发方式
|
||||||
|
默认是移入触发菜单,可以点击触发。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Trigger mode
|
||||||
|
The default trigger mode is `hover`, you can change it to `click`.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-dropdown :trigger="['click']">
|
||||||
|
<a class="ant-dropdown-link" href="#">
|
||||||
|
Click me <a-icon type="down" />
|
||||||
|
</a>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="0">
|
||||||
|
<a href="http://www.alipay.com/">1st menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="1">
|
||||||
|
<a href="http://www.taobao.com/">2nd menu item</a>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-divider />
|
||||||
|
<a-menu-item key="3">3rd menu item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
```
|
@ -0,0 +1,81 @@
|
|||||||
|
<script>
|
||||||
|
import Button from '../button'
|
||||||
|
import { ButtonGroupProps } from '../button/button-group'
|
||||||
|
import Icon from '../icon'
|
||||||
|
import Dropdown from './dropdown'
|
||||||
|
import PropTypes from '../_util/vue-types'
|
||||||
|
import { hasProp, getComponentFromProp } from '../_util/props-util'
|
||||||
|
import getDropdownProps from './getDropdownProps'
|
||||||
|
const DropdownProps = getDropdownProps()
|
||||||
|
const ButtonGroup = Button.Group
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
...ButtonGroupProps,
|
||||||
|
...DropdownProps,
|
||||||
|
type: PropTypes.oneOf(['primary', 'ghost', 'dashed', 'default']).def('default'),
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
prefixCls: PropTypes.string.def('ant-dropdown-button'),
|
||||||
|
placement: DropdownProps.placement.def('bottomRight'),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick (e) {
|
||||||
|
this.$emit('click', e)
|
||||||
|
},
|
||||||
|
onVisibleChange (val) {
|
||||||
|
this.$emit('visibleChange', val)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'visible',
|
||||||
|
event: 'visibleChange',
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
const {
|
||||||
|
type, disabled,
|
||||||
|
prefixCls, trigger, align,
|
||||||
|
visible, placement, getPopupContainer,
|
||||||
|
...restProps
|
||||||
|
} = this.$props
|
||||||
|
|
||||||
|
const dropdownProps = {
|
||||||
|
props: {
|
||||||
|
align,
|
||||||
|
disabled,
|
||||||
|
trigger: disabled ? [] : trigger,
|
||||||
|
placement,
|
||||||
|
getPopupContainer,
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
visibleChange: this.onVisibleChange,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if (hasProp(this, 'visible')) {
|
||||||
|
dropdownProps.visible = visible
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonGroup
|
||||||
|
{...restProps}
|
||||||
|
class={prefixCls}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type={type}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={this.onClick}
|
||||||
|
>
|
||||||
|
{this.$slots.default}
|
||||||
|
</Button>
|
||||||
|
<Dropdown {...dropdownProps}>
|
||||||
|
<template slot='overlay'>
|
||||||
|
{getComponentFromProp(this, 'overlay')}
|
||||||
|
</template>
|
||||||
|
<Button type={type}>
|
||||||
|
<Icon type='down' />
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
</ButtonGroup>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
@ -0,0 +1,76 @@
|
|||||||
|
<script>
|
||||||
|
import RcDropdown from './src/dropdown'
|
||||||
|
import DropdownButton from './dropdown-button'
|
||||||
|
// import warning from '../_util/warning'
|
||||||
|
import PropTypes from '../_util/vue-types'
|
||||||
|
import { cloneElement, getPropsData } from '../_util/vnode'
|
||||||
|
import { getOptionProps } from '../_util/props-util'
|
||||||
|
import getDropdownProps from './getDropdownProps'
|
||||||
|
const DropdownProps = getDropdownProps()
|
||||||
|
const Dropdown = {
|
||||||
|
props: {
|
||||||
|
...DropdownProps,
|
||||||
|
prefixCls: PropTypes.string.def('ant-dropdown'),
|
||||||
|
mouseEnterDelay: PropTypes.number.def(0.15),
|
||||||
|
mouseLeaveDelay: PropTypes.number.def(0.1),
|
||||||
|
placement: DropdownProps.placement.def('bottomLeft'),
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'visible',
|
||||||
|
event: 'visibleChange',
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTransitionName () {
|
||||||
|
const { placement = '', transitionName } = this.$props
|
||||||
|
if (transitionName !== undefined) {
|
||||||
|
return transitionName
|
||||||
|
}
|
||||||
|
if (placement.indexOf('top') >= 0) {
|
||||||
|
return 'slide-down'
|
||||||
|
}
|
||||||
|
return 'slide-up'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { $slots, prefixCls, trigger, disabled, $listeners } = this
|
||||||
|
const dropdownTrigger = cloneElement($slots.default, {
|
||||||
|
class: `${prefixCls}-trigger`,
|
||||||
|
disabled,
|
||||||
|
})
|
||||||
|
const overlay = $slots.overlay && $slots.overlay[0]
|
||||||
|
// menu cannot be selectable in dropdown defaultly
|
||||||
|
const overlayProps = overlay && getPropsData(overlay)
|
||||||
|
const selectable = (overlayProps && 'selectable' in overlayProps)
|
||||||
|
? overlayProps.selectable : false
|
||||||
|
const fixedModeOverlay = cloneElement(overlay, {
|
||||||
|
props: {
|
||||||
|
mode: 'vertical',
|
||||||
|
selectable,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const dropdownProps = {
|
||||||
|
props: {
|
||||||
|
...getOptionProps(this),
|
||||||
|
transitionName: this.getTransitionName(),
|
||||||
|
trigger: disabled ? [] : trigger,
|
||||||
|
},
|
||||||
|
on: $listeners,
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<RcDropdown
|
||||||
|
{...dropdownProps}
|
||||||
|
>
|
||||||
|
{dropdownTrigger}
|
||||||
|
<template slot='overlay'>
|
||||||
|
{fixedModeOverlay}
|
||||||
|
</template>
|
||||||
|
</RcDropdown>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Dropdown.Button = DropdownButton
|
||||||
|
export default Dropdown
|
||||||
|
|
||||||
|
</script>
|
@ -0,0 +1,13 @@
|
|||||||
|
import PropTypes from '../_util/vue-types'
|
||||||
|
export default () => ({
|
||||||
|
trigger: PropTypes.array.def(['hover']),
|
||||||
|
overlay: PropTypes.any,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
align: PropTypes.object,
|
||||||
|
getPopupContainer: PropTypes.func,
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
transitionName: PropTypes.string,
|
||||||
|
placement: PropTypes.oneOf(['topLeft', 'topCenter', 'topRight', 'bottomLeft', 'bottomCenter', 'bottomRight']),
|
||||||
|
forceRender: PropTypes.bool,
|
||||||
|
})
|
@ -0,0 +1,43 @@
|
|||||||
|
## API
|
||||||
|
|
||||||
|
### Dropdown
|
||||||
|
|
||||||
|
| Property | Description | Type | Default |
|
||||||
|
| -------- | ----------- | ---- | ------- |
|
||||||
|
| disabled | whether the dropdown menu is disabled | boolean | - |
|
||||||
|
| getPopupContainer | to set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. [example](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | `() => document.body` |
|
||||||
|
| overlay(slot) | the dropdown menu | [Menu](#/components/us/menu) | - |
|
||||||
|
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| visible(v-model) | whether the dropdown menu is visible | boolean | - |
|
||||||
|
|
||||||
|
### events
|
||||||
|
| Events Name | Description | Arguments |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| visibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | function(visible) |
|
||||||
|
|
||||||
|
You should use [Menu](#/components/us/menu/) as `overlay`. The menu items and dividers are also available by using `Menu.Item` and `Menu.Divider`.
|
||||||
|
|
||||||
|
> Warning: You must set a unique `key` for `Menu.Item`.
|
||||||
|
>
|
||||||
|
> Menu of Dropdown is unselectable by default, you can make it selectable via `<Menu selectable>`.
|
||||||
|
|
||||||
|
### Dropdown.Button
|
||||||
|
|
||||||
|
| Property | Description | Type | Default |
|
||||||
|
| -------- | ----------- | ---- | ------- |
|
||||||
|
| disabled | whether the dropdown menu is disabled | boolean | - |
|
||||||
|
| overlay(slot) | the dropdown menu | [Menu](#/components/us/menu) | - |
|
||||||
|
| placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| size | size of the button, the same as [Button](#/components/us/button) | string | `default` |
|
||||||
|
| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| type | type of the button, the same as [Button](#/components/us/button) | string | `default` |
|
||||||
|
| visible | whether the dropdown menu is visible | boolean | - |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Dropdown.Button events
|
||||||
|
| Events Name | Description | Arguments |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| click | a callback function, the same as [Button](#/components/us/button), which will be executed when you click the button on the left | Function |
|
||||||
|
| visibleChange | a callback function takes an argument: `visible`, is executed when the visible state is changed | Function |
|
@ -0,0 +1,8 @@
|
|||||||
|
import Dropdown from './dropdown'
|
||||||
|
import DropdownButton from './dropdown-button'
|
||||||
|
|
||||||
|
export { DropDownProps } from './dropdown'
|
||||||
|
export { DropdownButtonProps } from './dropdown-button'
|
||||||
|
|
||||||
|
Dropdown.Button = DropdownButton
|
||||||
|
export default Dropdown
|
@ -0,0 +1,42 @@
|
|||||||
|
## API
|
||||||
|
|
||||||
|
属性如下
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| disabled | 菜单是否禁用 | boolean | - |
|
||||||
|
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` |
|
||||||
|
| overlay(slot) | 菜单 | [Menu](#/components/cn/menu) | - |
|
||||||
|
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| visible(v-model) | 菜单是否显示 | boolean | - |
|
||||||
|
|
||||||
|
`overlay` 菜单使用 [Menu](#/components/cn/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`。
|
||||||
|
|
||||||
|
> 注意: Menu.Item 必须设置唯一的 key 属性。
|
||||||
|
>
|
||||||
|
> Dropdown 下的 Menu 默认不可选中。如果需要菜单可选中,可以指定 `<Menu selectable>`.
|
||||||
|
|
||||||
|
### 事件
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| visibleChange | 菜单显示状态改变时调用,参数为 visible | function(visible) |
|
||||||
|
|
||||||
|
|
||||||
|
### Dropdown.Button
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| disabled | 菜单是否禁用 | boolean | - |
|
||||||
|
| overlay(slot) | 菜单 | [Menu](#/components/cn/menu/) | - |
|
||||||
|
| placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` |
|
||||||
|
| size | 按钮大小,和 [Button](#/components/cn/button/) 一致 | string | 'default' |
|
||||||
|
| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` |
|
||||||
|
| type | 按钮类型,和 [Button](#/components/cn/button/) 一致 | string | 'default' |
|
||||||
|
| visible(v-model) | 菜单是否显示 | boolean | - |
|
||||||
|
|
||||||
|
### Dropdown.Button事件
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| click | 点击左侧按钮的回调,和 [Button](#/components/cn/button/) 一致 | Function |
|
||||||
|
| visibleChange | 菜单显示状态改变时调用,参数为 visible | function(visible) |
|
@ -0,0 +1,157 @@
|
|||||||
|
<script>
|
||||||
|
import PropTypes from '../../_util/vue-types'
|
||||||
|
import Trigger from '../../trigger'
|
||||||
|
import placements from './placements'
|
||||||
|
import { hasProp } from '../../_util/props-util'
|
||||||
|
import BaseMixin from '../../_util/BaseMixin'
|
||||||
|
import { cloneElement, getEvents } from '../../_util/vnode'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [BaseMixin],
|
||||||
|
props: {
|
||||||
|
minOverlayWidthMatchTrigger: PropTypes.bool.def(true),
|
||||||
|
prefixCls: PropTypes.string.def('rc-dropdown'),
|
||||||
|
transitionName: PropTypes.string,
|
||||||
|
overlayClassName: PropTypes.string.def(''),
|
||||||
|
animation: PropTypes.any,
|
||||||
|
align: PropTypes.object,
|
||||||
|
overlayStyle: PropTypes.object.def({}),
|
||||||
|
placement: PropTypes.string.def('bottomLeft'),
|
||||||
|
trigger: PropTypes.array.def(['hover']),
|
||||||
|
showAction: PropTypes.array.def([]),
|
||||||
|
hideAction: PropTypes.array.def([]),
|
||||||
|
getPopupContainer: PropTypes.func,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
defaultVisible: PropTypes.bool.def(false),
|
||||||
|
mouseEnterDelay: PropTypes.number.def(0.15),
|
||||||
|
mouseLeaveDelay: PropTypes.number.def(0.1),
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
let sVisible = this.defaultVisible
|
||||||
|
if (hasProp(this, 'visible')) {
|
||||||
|
sVisible = this.visible
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
sVisible,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible (val) {
|
||||||
|
if (val !== undefined) {
|
||||||
|
this.setState({
|
||||||
|
sVisible: val,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick (e) {
|
||||||
|
// do no call onVisibleChange, if you need click to hide, use onClick and control visible
|
||||||
|
if (!hasProp(this, 'visible')) {
|
||||||
|
this.setState({
|
||||||
|
sVisible: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$emit('overlayClick', e)
|
||||||
|
if (this.childOriginEvents.click) {
|
||||||
|
this.childOriginEvents.click(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onVisibleChange (visible) {
|
||||||
|
if (!hasProp(this, 'visible')) {
|
||||||
|
this.setState({
|
||||||
|
sVisible: visible,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.__emit('visibleChange', visible)
|
||||||
|
},
|
||||||
|
|
||||||
|
getMenuElement () {
|
||||||
|
const child = this.$slots.overlay[0]
|
||||||
|
const events = getEvents(child)
|
||||||
|
if (!events._ANT_DROPDOWN_EVENT_HACK) {
|
||||||
|
this.childOriginEvents = events
|
||||||
|
}
|
||||||
|
const { prefixCls } = this.$props
|
||||||
|
const extraOverlayProps = {
|
||||||
|
prefixCls: `${prefixCls}-menu`,
|
||||||
|
}
|
||||||
|
const overlay = this.$slots.overlay[0]
|
||||||
|
return cloneElement(overlay, {
|
||||||
|
props: extraOverlayProps,
|
||||||
|
on: {
|
||||||
|
click: this.onClick,
|
||||||
|
_ANT_DROPDOWN_EVENT_HACK: () => {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
getPopupDomNode () {
|
||||||
|
return this.$refs.trigger.getPopupDomNode()
|
||||||
|
},
|
||||||
|
|
||||||
|
afterVisibleChange (visible) {
|
||||||
|
if (visible && this.$props.minOverlayWidthMatchTrigger) {
|
||||||
|
const overlayNode = this.getPopupDomNode()
|
||||||
|
const rootNode = this.$el
|
||||||
|
if (rootNode && overlayNode && rootNode.offsetWidth > overlayNode.offsetWidth) {
|
||||||
|
overlayNode.style.width = `${rootNode.offsetWidth}px`
|
||||||
|
if (this.$refs.trigger &&
|
||||||
|
this.$refs.trigger._component &&
|
||||||
|
this.$refs.trigger._component.alignInstance) {
|
||||||
|
this.$refs.trigger._component.alignInstance.forceAlign()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const {
|
||||||
|
prefixCls,
|
||||||
|
transitionName, animation,
|
||||||
|
align, placement, getPopupContainer,
|
||||||
|
showAction, hideAction,
|
||||||
|
overlayClassName, overlayStyle,
|
||||||
|
trigger, ...otherProps
|
||||||
|
} = this.$props
|
||||||
|
|
||||||
|
const triggerProps = {
|
||||||
|
props: {
|
||||||
|
...otherProps,
|
||||||
|
prefixCls,
|
||||||
|
popupClassName: overlayClassName,
|
||||||
|
popupStyle: overlayStyle,
|
||||||
|
builtinPlacements: placements,
|
||||||
|
action: trigger,
|
||||||
|
showAction,
|
||||||
|
hideAction,
|
||||||
|
popupPlacement: placement,
|
||||||
|
popupAlign: align,
|
||||||
|
popupTransitionName: transitionName,
|
||||||
|
popupAnimation: animation,
|
||||||
|
popupVisible: this.sVisible,
|
||||||
|
afterPopupVisibleChange: this.afterVisibleChange,
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
popupVisibleChange: this.onVisibleChange,
|
||||||
|
},
|
||||||
|
ref: 'trigger',
|
||||||
|
}
|
||||||
|
const child = this.$slots.default && this.$slots.default[0]
|
||||||
|
return (
|
||||||
|
<Trigger {...triggerProps}>
|
||||||
|
{child && !child.tag
|
||||||
|
? <span>{child}</span>
|
||||||
|
: child}
|
||||||
|
<template slot='popup'>
|
||||||
|
{this.$slots.overlay && this.getMenuElement()}
|
||||||
|
</template>
|
||||||
|
</Trigger>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
@ -0,0 +1,2 @@
|
|||||||
|
import Dropdown from './Dropdown'
|
||||||
|
export default Dropdown
|
@ -0,0 +1,47 @@
|
|||||||
|
const autoAdjustOverflow = {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetOffset = [0, 0]
|
||||||
|
|
||||||
|
export const placements = {
|
||||||
|
topLeft: {
|
||||||
|
points: ['bl', 'tl'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, -4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
topCenter: {
|
||||||
|
points: ['bc', 'tc'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, -4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
topRight: {
|
||||||
|
points: ['br', 'tr'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, -4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
bottomLeft: {
|
||||||
|
points: ['tl', 'bl'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, 4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
bottomCenter: {
|
||||||
|
points: ['tc', 'bc'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, 4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
bottomRight: {
|
||||||
|
points: ['tr', 'br'],
|
||||||
|
overflow: autoAdjustOverflow,
|
||||||
|
offset: [0, 4],
|
||||||
|
targetOffset,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default placements
|
@ -0,0 +1,5 @@
|
|||||||
|
import '../../style/index.less'
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
|
// style dependencies
|
||||||
|
import '../../button/style'
|
@ -0,0 +1,250 @@
|
|||||||
|
@import "../../style/themes/default";
|
||||||
|
@import "../../style/mixins/index";
|
||||||
|
|
||||||
|
@dropdown-prefix-cls: ~"@{ant-prefix}-dropdown";
|
||||||
|
|
||||||
|
.@{dropdown-prefix-cls} {
|
||||||
|
.reset-component;
|
||||||
|
position: absolute;
|
||||||
|
left: -9999px;
|
||||||
|
top: -9999px;
|
||||||
|
z-index: @zindex-dropdown;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&-wrap {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{iconfont-css-prefix}-down:before {
|
||||||
|
transition: transform .2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-wrap-open {
|
||||||
|
.@{iconfont-css-prefix}-down:before {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-hidden,
|
||||||
|
&-menu-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-menu {
|
||||||
|
outline: none;
|
||||||
|
position: relative;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
text-align: left;
|
||||||
|
background-color: @component-background;
|
||||||
|
border-radius: @border-radius-base;
|
||||||
|
box-shadow: @box-shadow-base;
|
||||||
|
background-clip: padding-box;
|
||||||
|
|
||||||
|
&-item-group-title {
|
||||||
|
color: @text-color-secondary;
|
||||||
|
padding: 5px @control-padding-horizontal;
|
||||||
|
transition: all .3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-popup {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-item,
|
||||||
|
&-submenu-title {
|
||||||
|
padding: 5px @control-padding-horizontal;
|
||||||
|
margin: 0;
|
||||||
|
clear: both;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: normal;
|
||||||
|
color: @text-color;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all .3s;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
color: @text-color;
|
||||||
|
display: block;
|
||||||
|
padding: 5px @control-padding-horizontal;
|
||||||
|
margin: -5px -@control-padding-horizontal;
|
||||||
|
transition: all .3s;
|
||||||
|
&:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-selected,
|
||||||
|
&-selected > a {
|
||||||
|
color: @primary-color;
|
||||||
|
background-color: @item-active-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: @item-hover-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled {
|
||||||
|
color: @disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @disabled-color;
|
||||||
|
background-color: @component-background;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child,
|
||||||
|
&:first-child > a {
|
||||||
|
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child,
|
||||||
|
&:last-child > a {
|
||||||
|
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:only-child,
|
||||||
|
&:only-child > a {
|
||||||
|
border-radius: @border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-divider {
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: @border-color-split;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-arrow {
|
||||||
|
position: absolute;
|
||||||
|
right: @padding-xs;
|
||||||
|
&:after {
|
||||||
|
font-family: "anticon" !important;
|
||||||
|
font-style: normal;
|
||||||
|
content: "\e61f";
|
||||||
|
color: @text-color-secondary;
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-title {
|
||||||
|
padding-right: 26px;
|
||||||
|
&:first-child,
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-vertical {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu-vertical > & {
|
||||||
|
top: 0;
|
||||||
|
left: 100%;
|
||||||
|
position: absolute;
|
||||||
|
min-width: 100%;
|
||||||
|
margin-left: 4px;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
|
||||||
|
&,
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-arrow:after {
|
||||||
|
color: @disabled-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-submenu:first-child &-submenu-title {
|
||||||
|
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submenu:last-child &-submenu-title {
|
||||||
|
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-down-enter.slide-down-enter-active&-placement-bottomLeft,
|
||||||
|
&.slide-down-appear.slide-down-appear-active&-placement-bottomLeft,
|
||||||
|
&.slide-down-enter.slide-down-enter-active&-placement-bottomCenter,
|
||||||
|
&.slide-down-appear.slide-down-appear-active&-placement-bottomCenter,
|
||||||
|
&.slide-down-enter.slide-down-enter-active&-placement-bottomRight,
|
||||||
|
&.slide-down-appear.slide-down-appear-active&-placement-bottomRight {
|
||||||
|
animation-name: antSlideUpIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topLeft,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topLeft,
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topCenter,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topCenter,
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topRight,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topRight {
|
||||||
|
animation-name: antSlideDownIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-down-leave.slide-down-leave-active&-placement-bottomLeft,
|
||||||
|
&.slide-down-leave.slide-down-leave-active&-placement-bottomCenter,
|
||||||
|
&.slide-down-leave.slide-down-leave-active&-placement-bottomRight {
|
||||||
|
animation-name: antSlideUpOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topLeft,
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topCenter,
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topRight {
|
||||||
|
animation-name: antSlideDownOut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{dropdown-prefix-cls}-trigger,
|
||||||
|
.@{dropdown-prefix-cls}-link {
|
||||||
|
.@{iconfont-css-prefix}-down {
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{dropdown-prefix-cls}-button {
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.@{ant-prefix}-btn-group > .@{ant-prefix}-btn:last-child:not(:first-child) {
|
||||||
|
padding-left: @padding-xs;
|
||||||
|
padding-right: @padding-xs;
|
||||||
|
}
|
||||||
|
.@{iconfont-css-prefix}-down {
|
||||||
|
.iconfont-size-under-12px(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/ant-design/ant-design/issues/4903
|
||||||
|
.@{dropdown-prefix-cls}-menu-dark {
|
||||||
|
&,
|
||||||
|
.@{dropdown-prefix-cls}-menu {
|
||||||
|
background: @menu-dark-bg;
|
||||||
|
}
|
||||||
|
.@{dropdown-prefix-cls}-menu-item,
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-title,
|
||||||
|
.@{dropdown-prefix-cls}-menu-item > a {
|
||||||
|
color: @text-color-secondary-dark;
|
||||||
|
.@{dropdown-prefix-cls}-menu-submenu-arrow:after {
|
||||||
|
color: @text-color-secondary-dark;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.@{dropdown-prefix-cls}-menu-item-selected {
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
> a {
|
||||||
|
background: @primary-color;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue