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 \ No newline at end of file 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 \ No newline at end of file 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 \ No newline at end of file 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 \ No newline at end of file 8 \ No newline at end of file
src/components/select/dropdown.vue
@@ -5,6 +5,12 @@ @@ -5,6 +5,12 @@
5 import Popper from 'popper.js'; 5 import Popper from 'popper.js';
6 6
7 export default { 7 export default {
  8 + props: {
  9 + placement: {
  10 + type: String,
  11 + default: 'bottom-start'
  12 + }
  13 + },
8 data () { 14 data () {
9 return { 15 return {
10 popper: null 16 popper: null
@@ -20,7 +26,7 @@ @@ -20,7 +26,7 @@
20 this.$nextTick(() => { 26 this.$nextTick(() => {
21 this.popper = new Popper(this.$parent.$els.reference, this.$el, { 27 this.popper = new Popper(this.$parent.$els.reference, this.$el, {
22 gpuAcceleration: false, 28 gpuAcceleration: false,
23 - placement: 'bottom-start', 29 + placement: this.placement,
24 boundariesPadding: 0, 30 boundariesPadding: 0,
25 forceAbsolute: true, 31 forceAbsolute: true,
26 boundariesElement: 'body' 32 boundariesElement: 'body'
@@ -12,6 +12,7 @@ import Cascader from &#39;./components/cascader&#39;; @@ -12,6 +12,7 @@ import Cascader from &#39;./components/cascader&#39;;
12 import Checkbox from './components/checkbox'; 12 import Checkbox from './components/checkbox';
13 import Circle from './components/circle'; 13 import Circle from './components/circle';
14 import Collapse from './components/collapse'; 14 import Collapse from './components/collapse';
  15 +import Dropdown from './components/dropdown';
15 import Icon from './components/icon'; 16 import Icon from './components/icon';
16 import Input from './components/input'; 17 import Input from './components/input';
17 import InputNumber from './components/input-number'; 18 import InputNumber from './components/input-number';
@@ -49,6 +50,9 @@ const iview = { @@ -49,6 +50,9 @@ const iview = {
49 Checkbox, 50 Checkbox,
50 CheckboxGroup: Checkbox.Group, 51 CheckboxGroup: Checkbox.Group,
51 Circle, 52 Circle,
  53 + Dropdown,
  54 + DropdownItem: Dropdown.Item,
  55 + DropdownMenu: Dropdown.Menu,
52 iCol: Col, 56 iCol: Col,
53 Collapse, 57 Collapse,
54 Icon, 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 \ No newline at end of file 18 \ No newline at end of file
src/styles/components/index.less
@@ -28,4 +28,5 @@ @@ -28,4 +28,5 @@
28 @import "slider"; 28 @import "slider";
29 @import "cascader"; 29 @import "cascader";
30 @import "transfer"; 30 @import "transfer";
31 -@import "table";  
32 \ No newline at end of file 31 \ No newline at end of file
  32 +@import "table";
  33 +@import "dropdown";
33 \ No newline at end of file 34 \ No newline at end of file
src/styles/mixins/input.less
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 .input-small() { 27 .input-small() {
28 padding: @input-padding-vertical-small @input-padding-horizontal; 28 padding: @input-padding-vertical-small @input-padding-horizontal;
29 height: @input-height-small; 29 height: @input-height-small;
30 - border-radius: @border-radius-small; 30 + border-radius: @btn-border-radius-small;
31 } 31 }
32 32
33 .input() { 33 .input() {
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 padding: @input-padding-vertical-base @input-padding-horizontal; 38 padding: @input-padding-vertical-base @input-padding-horizontal;
39 font-size: @font-size-small; 39 font-size: @font-size-small;
40 border: 1px solid @input-border-color; 40 border: 1px solid @input-border-color;
41 - border-radius: @border-radius-base; 41 + border-radius: @btn-border-radius;
42 color: @input-color; 42 color: @input-color;
43 background-color: @input-bg; 43 background-color: @input-bg;
44 background-image: none; 44 background-image: none;
src/styles/mixins/select.less
@@ -37,6 +37,18 @@ @@ -37,6 +37,18 @@
37 &-selected&-focus { 37 &-selected&-focus {
38 background: shade(@selected-color, 10%); 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 .@{size-class}-large .@{item-class} { 54 .@{size-class}-large .@{item-class} {
@@ -42,6 +42,7 @@ li + li { @@ -42,6 +42,7 @@ li + li {
42 <li><a v-link="'/cascader'">Cascader</a></li> 42 <li><a v-link="'/cascader'">Cascader</a></li>
43 <li><a v-link="'/transfer'">Transfer</a></li> 43 <li><a v-link="'/transfer'">Transfer</a></li>
44 <li><a v-link="'/table'">Table</a></li> 44 <li><a v-link="'/table'">Table</a></li>
  45 + <li><a v-link="'/dropdown'">Dropdown</a></li>
45 </ul> 46 </ul>
46 </nav> 47 </nav>
47 <router-view></router-view> 48 <router-view></router-view>
@@ -107,6 +107,11 @@ router.map({ @@ -107,6 +107,11 @@ router.map({
107 component: function (resolve) { 107 component: function (resolve) {
108 require(['./routers/table.vue'], resolve); 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 \ No newline at end of file 34 \ No newline at end of file