add Dropdown component
add Dropdown component
This commit is contained in:
parent
0f4ccf4486
commit
ab8aaf958a
13 changed files with 235 additions and 4 deletions
50
src/components/dropdown/dropdown-item.vue
Normal file
50
src/components/dropdown/dropdown-item.vue
Normal file
|
@ -0,0 +1,50 @@
|
|||
<template>
|
||||
<li :class="classes" @click="handleClick"><slot></slot></li>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-dropdown-item';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
key: {
|
||||
type: [String, Number]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
divided: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-disabled`]: this.disabled,
|
||||
[`${prefixCls}-selected`]: this.selected,
|
||||
[`${prefixCls}-divided`]: this.divided
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
if (this.disabled) {
|
||||
this.$nextTick(() => {
|
||||
this.$parent.$parent.visible = true;
|
||||
});
|
||||
} else {
|
||||
this.$parent.$parent.visible = false;
|
||||
}
|
||||
this.$parent.$parent.$emit('on-click', this.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
6
src/components/dropdown/dropdown-menu.vue
Normal file
6
src/components/dropdown/dropdown-menu.vue
Normal file
|
@ -0,0 +1,6 @@
|
|||
<template>
|
||||
<ul class="ivu-dropdown-menu"><slot></slot></ul>
|
||||
</template>
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
89
src/components/dropdown/dropdown.vue
Normal file
89
src/components/dropdown/dropdown.vue
Normal file
|
@ -0,0 +1,89 @@
|
|||
<template>
|
||||
<div
|
||||
:class="[prefixCls]"
|
||||
@click="handleClick"
|
||||
@mouseenter="handleMouseenter"
|
||||
@mouseleave="handleMouseleave"
|
||||
v-clickoutside="handleClose">
|
||||
<div :class="[prefixCls-rel]" v-el:reference><slot></slot></div>
|
||||
<Drop v-show="visible" :placement="placement" transition="slide-up"><slot name="list"></slot></Drop>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Drop from '../select/dropdown.vue';
|
||||
import clickoutside from '../../directives/clickoutside';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-dropdown';
|
||||
|
||||
export default {
|
||||
directives: { clickoutside },
|
||||
components: { Drop },
|
||||
props: {
|
||||
trigger: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['click', 'hover']);
|
||||
},
|
||||
default: 'hover'
|
||||
},
|
||||
align: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['left', 'center', 'right']);
|
||||
},
|
||||
default: 'center'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
placement () {
|
||||
return this.align === 'left' ? 'bottom-start' : this.align === 'center' ? 'bottom' : 'bottom-end';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
if (this.trigger !== 'click') {
|
||||
return false;
|
||||
}
|
||||
this.visible = !this.visible;
|
||||
},
|
||||
handleMouseenter () {
|
||||
if (this.trigger !== 'hover') {
|
||||
return false;
|
||||
}
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.visible = true;
|
||||
}, 250);
|
||||
},
|
||||
handleMouseleave () {
|
||||
if (this.trigger !== 'hover') {
|
||||
return false;
|
||||
}
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.visible = false;
|
||||
}, 150);
|
||||
},
|
||||
handleClose () {
|
||||
if (this.trigger !== 'click') {
|
||||
return false;
|
||||
}
|
||||
this.visible = false;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible (val) {
|
||||
if (val) {
|
||||
this.$broadcast('on-update-popper');
|
||||
} else {
|
||||
this.$broadcast('on-destroy-popper');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
7
src/components/dropdown/index.js
Normal file
7
src/components/dropdown/index.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import Dropdown from './dropdown.vue';
|
||||
import DropdownMenu from './dropdown-menu.vue';
|
||||
import DropdownItem from './dropdown-item.vue';
|
||||
|
||||
Dropdown.Menu = DropdownMenu;
|
||||
Dropdown.Item = DropdownItem;
|
||||
export default Dropdown;
|
|
@ -5,6 +5,12 @@
|
|||
import Popper from 'popper.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
placement: {
|
||||
type: String,
|
||||
default: 'bottom-start'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
popper: null
|
||||
|
@ -20,7 +26,7 @@
|
|||
this.$nextTick(() => {
|
||||
this.popper = new Popper(this.$parent.$els.reference, this.$el, {
|
||||
gpuAcceleration: false,
|
||||
placement: 'bottom-start',
|
||||
placement: this.placement,
|
||||
boundariesPadding: 0,
|
||||
forceAbsolute: true,
|
||||
boundariesElement: 'body'
|
||||
|
|
|
@ -12,6 +12,7 @@ import Cascader from './components/cascader';
|
|||
import Checkbox from './components/checkbox';
|
||||
import Circle from './components/circle';
|
||||
import Collapse from './components/collapse';
|
||||
import Dropdown from './components/dropdown';
|
||||
import Icon from './components/icon';
|
||||
import Input from './components/input';
|
||||
import InputNumber from './components/input-number';
|
||||
|
@ -49,6 +50,9 @@ const iview = {
|
|||
Checkbox,
|
||||
CheckboxGroup: Checkbox.Group,
|
||||
Circle,
|
||||
Dropdown,
|
||||
DropdownItem: Dropdown.Item,
|
||||
DropdownMenu: Dropdown.Menu,
|
||||
iCol: Col,
|
||||
Collapse,
|
||||
Icon,
|
||||
|
|
17
src/styles/components/dropdown.less
Normal file
17
src/styles/components/dropdown.less
Normal file
|
@ -0,0 +1,17 @@
|
|||
@dropdown-prefix-cls: ~"@{css-prefix}dropdown";
|
||||
@dropdown-item-prefix-cls: ~"@{dropdown-prefix-cls}-item";
|
||||
|
||||
.@{dropdown-prefix-cls} {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
&-rel{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-menu{
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.select-item(@dropdown-prefix-cls, @dropdown-item-prefix-cls);
|
|
@ -28,4 +28,5 @@
|
|||
@import "slider";
|
||||
@import "cascader";
|
||||
@import "transfer";
|
||||
@import "table";
|
||||
@import "table";
|
||||
@import "dropdown";
|
|
@ -27,7 +27,7 @@
|
|||
.input-small() {
|
||||
padding: @input-padding-vertical-small @input-padding-horizontal;
|
||||
height: @input-height-small;
|
||||
border-radius: @border-radius-small;
|
||||
border-radius: @btn-border-radius-small;
|
||||
}
|
||||
|
||||
.input() {
|
||||
|
@ -38,7 +38,7 @@
|
|||
padding: @input-padding-vertical-base @input-padding-horizontal;
|
||||
font-size: @font-size-small;
|
||||
border: 1px solid @input-border-color;
|
||||
border-radius: @border-radius-base;
|
||||
border-radius: @btn-border-radius;
|
||||
color: @input-color;
|
||||
background-color: @input-bg;
|
||||
background-image: none;
|
||||
|
|
|
@ -37,6 +37,18 @@
|
|||
&-selected&-focus {
|
||||
background: shade(@selected-color, 10%);
|
||||
}
|
||||
|
||||
&-divided{
|
||||
margin-top: 5px;
|
||||
border-top: 1px solid @border-color-split;
|
||||
&:before{
|
||||
content: '';
|
||||
height: 5px;
|
||||
display: block;
|
||||
margin: -7px -16px 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{size-class}-large .@{item-class} {
|
||||
|
|
|
@ -42,6 +42,7 @@ li + li {
|
|||
<li><a v-link="'/cascader'">Cascader</a></li>
|
||||
<li><a v-link="'/transfer'">Transfer</a></li>
|
||||
<li><a v-link="'/table'">Table</a></li>
|
||||
<li><a v-link="'/dropdown'">Dropdown</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<router-view></router-view>
|
||||
|
|
|
@ -107,6 +107,11 @@ router.map({
|
|||
component: function (resolve) {
|
||||
require(['./routers/table.vue'], resolve);
|
||||
}
|
||||
},
|
||||
'/dropdown': {
|
||||
component: function (resolve) {
|
||||
require(['./routers/dropdown.vue'], resolve);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
33
test/routers/dropdown.vue
Normal file
33
test/routers/dropdown.vue
Normal file
|
@ -0,0 +1,33 @@
|
|||
<style>
|
||||
body{
|
||||
padding: 50px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<Dropdown trigger="click" align="right" @on-click="click">
|
||||
<i-button type="primary">
|
||||
下拉菜单
|
||||
<Icon type="arrow-down-b"></Icon>
|
||||
</i-button>
|
||||
<Dropdown-menu slot="list">
|
||||
<Dropdown-item>张三</Dropdown-item>
|
||||
<Dropdown-item disabled>李四</Dropdown-item>
|
||||
<Dropdown-item>王五</Dropdown-item>
|
||||
<Dropdown-item divided>周六</Dropdown-item>
|
||||
</Dropdown-menu>
|
||||
</Dropdown>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {},
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
click (key) {
|
||||
console.log(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Add table
Reference in a new issue