Commit ab8aaf958a7ec317e06f0735e98264a0c700bfef

Authored by 梁灏
1 parent 0f4ccf44

add Dropdown component

add Dropdown component
src/components/dropdown/dropdown-item.vue 0 → 100644
  1 +<template>
  2 + <li :class="classes" @click="handleClick"><slot></slot></li>
  3 +</template>
  4 +<script>
  5 + const prefixCls = 'ivu-dropdown-item';
  6 +
  7 + export default {
  8 + props: {
  9 + key: {
  10 + type: [String, Number]
  11 + },
  12 + disabled: {
  13 + type: Boolean,
  14 + default: false
  15 + },
  16 + selected: {
  17 + type: Boolean,
  18 + default: false
  19 + },
  20 + divided: {
  21 + type: Boolean,
  22 + default: false
  23 + }
  24 + },
  25 + computed: {
  26 + classes () {
  27 + return [
  28 + `${prefixCls}`,
  29 + {
  30 + [`${prefixCls}-disabled`]: this.disabled,
  31 + [`${prefixCls}-selected`]: this.selected,
  32 + [`${prefixCls}-divided`]: this.divided
  33 + }
  34 + ]
  35 + }
  36 + },
  37 + methods: {
  38 + handleClick () {
  39 + if (this.disabled) {
  40 + this.$nextTick(() => {
  41 + this.$parent.$parent.visible = true;
  42 + });
  43 + } else {
  44 + this.$parent.$parent.visible = false;
  45 + }
  46 + this.$parent.$parent.$emit('on-click', this.key);
  47 + }
  48 + }
  49 + }
  50 +</script>
0 51 \ No newline at end of file
... ...
src/components/dropdown/dropdown-menu.vue 0 → 100644
  1 +<template>
  2 + <ul class="ivu-dropdown-menu"><slot></slot></ul>
  3 +</template>
  4 +<script>
  5 + export default {}
  6 +</script>
0 7 \ No newline at end of file
... ...
src/components/dropdown/dropdown.vue 0 → 100644
  1 +<template>
  2 + <div
  3 + :class="[prefixCls]"
  4 + @click="handleClick"
  5 + @mouseenter="handleMouseenter"
  6 + @mouseleave="handleMouseleave"
  7 + v-clickoutside="handleClose">
  8 + <div :class="[prefixCls-rel]" v-el:reference><slot></slot></div>
  9 + <Drop v-show="visible" :placement="placement" transition="slide-up"><slot name="list"></slot></Drop>
  10 + </div>
  11 +</template>
  12 +<script>
  13 + import Drop from '../select/dropdown.vue';
  14 + import clickoutside from '../../directives/clickoutside';
  15 + import { oneOf } from '../../utils/assist';
  16 +
  17 + const prefixCls = 'ivu-dropdown';
  18 +
  19 + export default {
  20 + directives: { clickoutside },
  21 + components: { Drop },
  22 + props: {
  23 + trigger: {
  24 + validator (value) {
  25 + return oneOf(value, ['click', 'hover']);
  26 + },
  27 + default: 'hover'
  28 + },
  29 + align: {
  30 + validator (value) {
  31 + return oneOf(value, ['left', 'center', 'right']);
  32 + },
  33 + default: 'center'
  34 + }
  35 + },
  36 + data () {
  37 + return {
  38 + prefixCls: prefixCls,
  39 + visible: false
  40 + }
  41 + },
  42 + computed: {
  43 + placement () {
  44 + return this.align === 'left' ? 'bottom-start' : this.align === 'center' ? 'bottom' : 'bottom-end';
  45 + }
  46 + },
  47 + methods: {
  48 + handleClick () {
  49 + if (this.trigger !== 'click') {
  50 + return false;
  51 + }
  52 + this.visible = !this.visible;
  53 + },
  54 + handleMouseenter () {
  55 + if (this.trigger !== 'hover') {
  56 + return false;
  57 + }
  58 + clearTimeout(this.timeout);
  59 + this.timeout = setTimeout(() => {
  60 + this.visible = true;
  61 + }, 250);
  62 + },
  63 + handleMouseleave () {
  64 + if (this.trigger !== 'hover') {
  65 + return false;
  66 + }
  67 + clearTimeout(this.timeout);
  68 + this.timeout = setTimeout(() => {
  69 + this.visible = false;
  70 + }, 150);
  71 + },
  72 + handleClose () {
  73 + if (this.trigger !== 'click') {
  74 + return false;
  75 + }
  76 + this.visible = false;
  77 + }
  78 + },
  79 + watch: {
  80 + visible (val) {
  81 + if (val) {
  82 + this.$broadcast('on-update-popper');
  83 + } else {
  84 + this.$broadcast('on-destroy-popper');
  85 + }
  86 + }
  87 + }
  88 + }
  89 +</script>
0 90 \ No newline at end of file
... ...
src/components/dropdown/index.js 0 → 100644
  1 +import Dropdown from './dropdown.vue';
  2 +import DropdownMenu from './dropdown-menu.vue';
  3 +import DropdownItem from './dropdown-item.vue';
  4 +
  5 +Dropdown.Menu = DropdownMenu;
  6 +Dropdown.Item = DropdownItem;
  7 +export default Dropdown;
0 8 \ No newline at end of file
... ...
src/components/select/dropdown.vue
... ... @@ -5,6 +5,12 @@
5 5 import Popper from 'popper.js';
6 6  
7 7 export default {
  8 + props: {
  9 + placement: {
  10 + type: String,
  11 + default: 'bottom-start'
  12 + }
  13 + },
8 14 data () {
9 15 return {
10 16 popper: null
... ... @@ -20,7 +26,7 @@
20 26 this.$nextTick(() => {
21 27 this.popper = new Popper(this.$parent.$els.reference, this.$el, {
22 28 gpuAcceleration: false,
23   - placement: 'bottom-start',
  29 + placement: this.placement,
24 30 boundariesPadding: 0,
25 31 forceAbsolute: true,
26 32 boundariesElement: 'body'
... ...
src/index.js
... ... @@ -12,6 +12,7 @@ import Cascader from &#39;./components/cascader&#39;;
12 12 import Checkbox from './components/checkbox';
13 13 import Circle from './components/circle';
14 14 import Collapse from './components/collapse';
  15 +import Dropdown from './components/dropdown';
15 16 import Icon from './components/icon';
16 17 import Input from './components/input';
17 18 import InputNumber from './components/input-number';
... ... @@ -49,6 +50,9 @@ const iview = {
49 50 Checkbox,
50 51 CheckboxGroup: Checkbox.Group,
51 52 Circle,
  53 + Dropdown,
  54 + DropdownItem: Dropdown.Item,
  55 + DropdownMenu: Dropdown.Menu,
52 56 iCol: Col,
53 57 Collapse,
54 58 Icon,
... ...
src/styles/components/dropdown.less 0 → 100644
  1 +@dropdown-prefix-cls: ~"@{css-prefix}dropdown";
  2 +@dropdown-item-prefix-cls: ~"@{dropdown-prefix-cls}-item";
  3 +
  4 +.@{dropdown-prefix-cls} {
  5 + display: inline-block;
  6 + position: relative;
  7 +
  8 + &-rel{
  9 + display: inline-block;
  10 + }
  11 +
  12 + &-menu{
  13 + min-width: 100px;
  14 + }
  15 +}
  16 +
  17 +.select-item(@dropdown-prefix-cls, @dropdown-item-prefix-cls);
0 18 \ No newline at end of file
... ...
src/styles/components/index.less
... ... @@ -28,4 +28,5 @@
28 28 @import "slider";
29 29 @import "cascader";
30 30 @import "transfer";
31   -@import "table";
32 31 \ No newline at end of file
  32 +@import "table";
  33 +@import "dropdown";
33 34 \ No newline at end of file
... ...
src/styles/mixins/input.less
... ... @@ -27,7 +27,7 @@
27 27 .input-small() {
28 28 padding: @input-padding-vertical-small @input-padding-horizontal;
29 29 height: @input-height-small;
30   - border-radius: @border-radius-small;
  30 + border-radius: @btn-border-radius-small;
31 31 }
32 32  
33 33 .input() {
... ... @@ -38,7 +38,7 @@
38 38 padding: @input-padding-vertical-base @input-padding-horizontal;
39 39 font-size: @font-size-small;
40 40 border: 1px solid @input-border-color;
41   - border-radius: @border-radius-base;
  41 + border-radius: @btn-border-radius;
42 42 color: @input-color;
43 43 background-color: @input-bg;
44 44 background-image: none;
... ...
src/styles/mixins/select.less
... ... @@ -37,6 +37,18 @@
37 37 &-selected&-focus {
38 38 background: shade(@selected-color, 10%);
39 39 }
  40 +
  41 + &-divided{
  42 + margin-top: 5px;
  43 + border-top: 1px solid @border-color-split;
  44 + &:before{
  45 + content: '';
  46 + height: 5px;
  47 + display: block;
  48 + margin: -7px -16px 0;
  49 + background-color: #fff;
  50 + }
  51 + }
40 52 }
41 53  
42 54 .@{size-class}-large .@{item-class} {
... ...
test/app.vue
... ... @@ -42,6 +42,7 @@ li + li {
42 42 <li><a v-link="'/cascader'">Cascader</a></li>
43 43 <li><a v-link="'/transfer'">Transfer</a></li>
44 44 <li><a v-link="'/table'">Table</a></li>
  45 + <li><a v-link="'/dropdown'">Dropdown</a></li>
45 46 </ul>
46 47 </nav>
47 48 <router-view></router-view>
... ...
test/main.js
... ... @@ -107,6 +107,11 @@ router.map({
107 107 component: function (resolve) {
108 108 require(['./routers/table.vue'], resolve);
109 109 }
  110 + },
  111 + '/dropdown': {
  112 + component: function (resolve) {
  113 + require(['./routers/dropdown.vue'], resolve);
  114 + }
110 115 }
111 116 });
112 117  
... ...
test/routers/dropdown.vue 0 → 100644
  1 +<style>
  2 + body{
  3 + padding: 50px;
  4 + }
  5 +</style>
  6 +<template>
  7 + <Dropdown trigger="click" align="right" @on-click="click">
  8 + <i-button type="primary">
  9 + 下拉菜单
  10 + <Icon type="arrow-down-b"></Icon>
  11 + </i-button>
  12 + <Dropdown-menu slot="list">
  13 + <Dropdown-item>张三</Dropdown-item>
  14 + <Dropdown-item disabled>李四</Dropdown-item>
  15 + <Dropdown-item>王五</Dropdown-item>
  16 + <Dropdown-item divided>周六</Dropdown-item>
  17 + </Dropdown-menu>
  18 + </Dropdown>
  19 +</template>
  20 +<script>
  21 + export default {
  22 + props: {},
  23 + data () {
  24 + return {}
  25 + },
  26 + computed: {},
  27 + methods: {
  28 + click (key) {
  29 + console.log(key)
  30 + }
  31 + }
  32 + }
  33 +</script>
0 34 \ No newline at end of file
... ...