Commit e05d728978cd6744f816f7a6b9c930048c94ae3d

Authored by 梁灏
1 parent 8778b343

update Menu

update Menu
src/components/dropdown/dropdown.vue
... ... @@ -4,10 +4,7 @@
4 4 v-clickoutside="handleClose"
5 5 @mouseenter="handleMouseenter"
6 6 @mouseleave="handleMouseleave">
7   - <div
8   - :class="[prefixCls-rel]"
9   - v-el:reference
10   - @click="handleClick"><slot></slot></div>
  7 + <div :class="[prefixCls-rel]" v-el:reference @click="handleClick"><slot></slot></div>
11 8 <Drop v-show="visible" :placement="placement" :transition="transition" v-ref:drop><slot name="list"></slot></Drop>
12 9 </div>
13 10 </template>
... ...
src/components/menu/menu-group.vue
1 1 <template>
2   -
  2 + <li :class="[prefixCls + '-item-group']">
  3 + <div :class="[prefixCls + '-item-group-title']">{{ title }}</div>
  4 + <ul><slot></slot></ul>
  5 + </li>
3 6 </template>
4 7 <script>
  8 + const prefixCls = 'ivu-menu';
  9 +
5 10 export default {
6   - props: {},
  11 + name: 'MenuGroup',
  12 + props: {
  13 + title: {
  14 + type: String,
  15 + default: ''
  16 + }
  17 + },
7 18 data () {
8   - return {}
  19 + return {
  20 + prefixCls: prefixCls
  21 + }
9 22 },
10   - computed: {},
11   - methods: {}
  23 + computed: {
  24 +
  25 + },
  26 + methods: {
  27 +
  28 + }
12 29 }
13 30 </script>
14 31 \ No newline at end of file
... ...
src/components/menu/menu-item.vue
1 1 <template>
2   -
  2 + <li :class="classes" @click.stop="handleClick"><slot></slot></li>
3 3 </template>
4 4 <script>
  5 + const prefixCls = 'ivu-menu';
  6 +
5 7 export default {
6   - props: {},
  8 + name: 'MenuItem',
  9 + props: {
  10 + key: {
  11 + type: [String, Number],
  12 + required: true
  13 + },
  14 + disabled: {
  15 + type: Boolean,
  16 + default: false
  17 + }
  18 + },
7 19 data () {
8   - return {}
  20 + return {
  21 + active: false
  22 + }
  23 + },
  24 + computed: {
  25 + classes () {
  26 + return [
  27 + `${prefixCls}-item`,
  28 + {
  29 + [`${prefixCls}-item-active`]: this.active,
  30 + [`${prefixCls}-item-selected`]: this.active,
  31 + [`${prefixCls}-item-disabled`]: this.disabled
  32 + }
  33 + ]
  34 + }
9 35 },
10   - computed: {},
11   - methods: {}
  36 + methods: {
  37 + handleClick () {
  38 + this.$dispatch('on-menu-item-select', this.key);
  39 + }
  40 + }
12 41 }
13 42 </script>
14 43 \ No newline at end of file
... ...
src/components/menu/menu.vue
1 1 <template>
2   -
  2 + <ul :class="classes"><slot></slot></ul>
3 3 </template>
4 4 <script>
  5 + import { oneOf } from '../../utils/assist';
  6 +
  7 + const prefixCls = 'ivu-menu';
  8 +
5 9 export default {
6   - props: {},
  10 + props: {
  11 + mode: {
  12 + validator (value) {
  13 + return oneOf(value, ['horizontal', 'vertical']);
  14 + },
  15 + default: 'vertical'
  16 + },
  17 + theme: {
  18 + validator (value) {
  19 + return oneOf(value, ['light', 'dark', 'primary']);
  20 + },
  21 + default: 'light'
  22 + },
  23 + activeKey: {
  24 + type: [String, Number]
  25 + },
  26 + openKeys: {
  27 + type: Array
  28 + },
  29 + accordion: {
  30 + type: Boolean,
  31 + default: false
  32 + }
  33 + },
7 34 data () {
8   - return {}
  35 + return {
  36 +
  37 + }
  38 + },
  39 + computed: {
  40 + classes () {
  41 + return [
  42 + `${prefixCls}`,
  43 + {
  44 + [`${prefixCls}-${this.mode}`]: this.mode,
  45 + [`${prefixCls}-${this.theme}`]: this.theme
  46 + }
  47 + ]
  48 + }
  49 + },
  50 + methods: {
  51 + updateActiveKey () {
  52 + this.$children.forEach((item, index) => {
  53 + if (!this.activeKey && index === 0) this.activeKey = item.key;
  54 +
  55 + if (item.$options.name === 'Submenu') {
  56 + item.active = false;
  57 + item.$children.forEach(subitem => {
  58 + if (subitem.$options.name === 'MenuGroup') {
  59 + subitem.$children.forEach(groupItem => {
  60 + if (groupItem.key === this.activeKey) {
  61 + groupItem.active = true;
  62 + groupItem.$parent.$parent.active = true;
  63 + } else {
  64 + groupItem.active = false;
  65 + }
  66 + })
  67 + } else {
  68 + if (subitem.key === this.activeKey) {
  69 + subitem.active = true;
  70 + subitem.$parent.active = true;
  71 + } else {
  72 + subitem.active = false;
  73 + }
  74 + }
  75 + })
  76 + } else {
  77 + item.active = item.key === this.activeKey;
  78 + }
  79 + })
  80 + }
  81 + },
  82 + compiled () {
  83 + this.updateActiveKey();
9 84 },
10   - computed: {},
11   - methods: {}
  85 + events: {
  86 + 'on-menu-item-select' (key) {
  87 + this.activeKey = key;
  88 + this.updateActiveKey();
  89 + this.$emit('on-select', key);
  90 + }
  91 + }
12 92 }
13 93 </script>
14 94 \ No newline at end of file
... ...
src/components/menu/submenu.vue
1 1 <template>
2   -
  2 + <li :class="classes" @mouseenter="handleMouseenter" @mouseleave="handleMouseleave">
  3 + <div :class="[prefixCls + '-title']" v-el:reference>
  4 + <span><slot name="title"></slot></span>
  5 + <Icon type="ios-arrow-down"></Icon>
  6 + </div>
  7 + <ul :class="[prefixCls]" v-if="mode === 'vertical'"></ul>
  8 + <Drop v-else v-show="opened" placement="bottom" transition="slide-up" v-ref:drop><slot></slot></Drop>
  9 + </li>
3 10 </template>
4 11 <script>
  12 + import Drop from '../select/dropdown.vue';
  13 + import Icon from '../icon/icon.vue';
  14 + const prefixCls = 'ivu-menu';
  15 +
5 16 export default {
6   - props: {},
  17 + name: 'Submenu',
  18 + components: { Icon, Drop },
  19 + props: {
  20 + key: {
  21 + type: [String, Number],
  22 + required: true
  23 + }
  24 + },
7 25 data () {
8   - return {}
  26 + return {
  27 + prefixCls: prefixCls,
  28 + active: false,
  29 + opened: false
  30 + }
  31 + },
  32 + computed: {
  33 + classes () {
  34 + return [
  35 + `${prefixCls}-submenu`,
  36 + {
  37 + [`${prefixCls}-item-active`]: this.active,
  38 + [`${prefixCls}-opened`]: this.opened
  39 + }
  40 + ]
  41 + },
  42 + mode () {
  43 + return this.$parent.mode;
  44 + }
  45 + },
  46 + methods: {
  47 + handleMouseenter () {
  48 + if (this.mode === 'vertical') return;
  49 + clearTimeout(this.timeout);
  50 + this.timeout = setTimeout(() => {
  51 + this.opened = true;
  52 + }, 250);
  53 + },
  54 + handleMouseleave () {
  55 + if (this.mode === 'vertical') return;
  56 + clearTimeout(this.timeout);
  57 + this.timeout = setTimeout(() => {
  58 + this.opened = false;
  59 + }, 150);
  60 + }
  61 + },
  62 + watch: {
  63 + mode (val) {
  64 + if (val === 'horizontal') {
  65 + this.$refs.drop.update();
  66 + }
  67 + },
  68 + opened (val) {
  69 + if (this.mode === 'vertical') return;
  70 + if (val) {
  71 + this.$refs.drop.update();
  72 + } else {
  73 + this.$refs.drop.destroy();
  74 + }
  75 + }
9 76 },
10   - computed: {},
11   - methods: {}
  77 + events: {
  78 + 'on-menu-item-select' () {
  79 + this.opened = false;
  80 + return true;
  81 + }
  82 + }
12 83 }
13 84 </script>
14 85 \ No newline at end of file
... ...
src/styles/components/menu.less
  1 +@menu-prefix-cls: ~"@{css-prefix}menu";
  2 +@menu-dropdown-item-prefix-cls: ~"@{menu-prefix-cls}-horizontal .@{menu-prefix-cls}-submenu .@{select-dropdown-prefix-cls} .@{menu-prefix-cls}-item";
  3 +
  4 +.@{menu-prefix-cls} {
  5 + display: block;
  6 + margin: 0;
  7 + padding: 0;
  8 + outline: none;
  9 + list-style: none;
  10 + color: @text-color;
  11 + font-size: @font-size-base;
  12 + position: relative;
  13 +
  14 + &-horizontal{
  15 + height: 60px;
  16 + line-height: 60px;
  17 +
  18 + &.@{menu-prefix-cls}-light{
  19 + &:after{
  20 + content: '';
  21 + display: block;
  22 + width: 100%;
  23 + height: 1px;
  24 + background: @border-color-base;
  25 + position: absolute;
  26 + bottom: 0;
  27 + left: 0;
  28 + }
  29 + }
  30 + }
  31 + &-vertical{
  32 + width: 240px;
  33 + &.@{menu-prefix-cls}-light{
  34 + &:after{
  35 + content: '';
  36 + display: block;
  37 + width: 1px;
  38 + height: 100%;
  39 + background: @border-color-base;
  40 + position: absolute;
  41 + top: 0;
  42 + bottom: 0;
  43 + right: 0;
  44 + }
  45 + }
  46 + }
  47 +
  48 + &-light{
  49 + background: #fff;
  50 + }
  51 + &-dark{
  52 + background: @title-color;
  53 + }
  54 + &-primary{
  55 + background: @primary-color;
  56 + }
  57 +
  58 + &-item{
  59 + display: block;
  60 + outline: none;
  61 + list-style: none;
  62 + font-size: @font-size-base;
  63 + position: relative;
  64 + z-index: 1;
  65 + cursor: pointer;
  66 + transition: all @transition-time @ease-in-out;
  67 +
  68 + .@{menu-prefix-cls}-light &{
  69 + color: @text-color;
  70 + }
  71 + .@{menu-prefix-cls}-dark &{
  72 + color: @subsidiary-color;
  73 + &-active, &:hover{
  74 + color: #fff;
  75 + }
  76 + }
  77 + .@{menu-prefix-cls}-primary &{
  78 + color: #fff;
  79 + &-active, &:hover{
  80 + background: @link-active-color;
  81 + }
  82 + }
  83 + }
  84 + &-horizontal &-item,
  85 + &-horizontal &-submenu
  86 + {
  87 + float: left;
  88 + padding: 0 20px;
  89 + position: relative;
  90 + cursor: pointer;
  91 + z-index: 1;
  92 + transition: all @transition-time @ease-in-out;
  93 + }
  94 +
  95 + &-light&-horizontal &-item, &-light&-horizontal &-submenu{
  96 + height: inherit;
  97 + line-height: inherit;
  98 + border-bottom: 2px solid transparent;
  99 + &-active, &:hover{
  100 + color: @primary-color;
  101 + border-bottom: 2px solid @primary-color;
  102 + }
  103 + }
  104 +
  105 + &-dark&-horizontal &-item{
  106 + &-active, &:hover{
  107 + color: #fff;
  108 + }
  109 + }
  110 +
  111 + &-primary&-horizontal &-item{
  112 + &-active, &:hover{
  113 + background: @link-active-color;
  114 + }
  115 + }
  116 +
  117 + &-horizontal &-submenu .@{select-dropdown-prefix-cls} {
  118 + width: 100%;
  119 + .@{menu-prefix-cls}-item{
  120 + height: auto;
  121 + line-height: normal;
  122 + border-bottom: 0;
  123 + float: none;
  124 + }
  125 + }
  126 +
  127 + &-item-group{
  128 + line-height: normal;
  129 + &-title {
  130 + padding-left: 8px;
  131 + font-size: 12px;
  132 + color: @legend-color;
  133 + height: 30px;
  134 + line-height: 30px;
  135 + }
  136 + }
  137 +}
  138 +.select-item(@menu-prefix-cls, @menu-dropdown-item-prefix-cls);
0 139 \ No newline at end of file
... ...
test/app.vue
... ... @@ -44,6 +44,7 @@ li + li {
44 44 <li><a v-link="'/table'">Table</a></li>
45 45 <li><a v-link="'/dropdown'">Dropdown</a></li>
46 46 <li><a v-link="'/tabs'">Tabs</a></li>
  47 + <li><a v-link="'/menu'">Menu</a></li>
47 48 </ul>
48 49 </nav>
49 50 <router-view></router-view>
... ...
test/main.js
... ... @@ -117,6 +117,11 @@ router.map({
117 117 component: function (resolve) {
118 118 require(['./routers/tabs.vue'], resolve);
119 119 }
  120 + },
  121 + '/menu': {
  122 + component: function (resolve) {
  123 + require(['./routers/menu.vue'], resolve);
  124 + }
120 125 }
121 126 });
122 127  
... ...
test/routers/menu.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <i-button @click="toggleMode">调整方向</i-button>
  4 + <Menu :mode="mode" active-key="1">
  5 + <Menu-item key="1">
  6 + <Icon type="ionic"></Icon>
  7 + <span>导航一</span>
  8 + </Menu-item>
  9 + <Menu-item key="2">导航二</Menu-item>
  10 + <Submenu key="3">
  11 + <span slot="title">导航三</span>
  12 + <Menu-group title="集合1">
  13 + <Menu-item key="3-1">导航三 - 一</Menu-item>
  14 + <Menu-item key="3-2">导航三 - 二</Menu-item>
  15 + </Menu-group>
  16 + <Menu-group title="集合2">
  17 + <Menu-item key="3-3">导航三 - 三</Menu-item>
  18 + <Menu-item key="3-4">导航三 - 四</Menu-item>
  19 + </Menu-group>
  20 + </Submenu>
  21 + <Menu-item key="4">导航四</Menu-item>
  22 + </Menu>
  23 + <br><br>
  24 + <!--<Menu mode="horizontal" theme="dark" active-key="1">-->
  25 + <!--<Menu-item key="1">-->
  26 + <!--<Icon type="ionic"></Icon>-->
  27 + <!--<span>导航一</span>-->
  28 + <!--</Menu-item>-->
  29 + <!--<Menu-item key="2">导航二</Menu-item>-->
  30 + <!--<Submenu key="3">-->
  31 + <!--<span slot="title">导航三</span>-->
  32 + <!--<Menu-item key="3-1">导航三 - 一</Menu-item>-->
  33 + <!--<Menu-item key="3-2">导航三 - 二</Menu-item>-->
  34 + <!--<Menu-item key="3-3">导航三 - 三</Menu-item>-->
  35 + <!--</Submenu>-->
  36 + <!--<Menu-item key="4">导航四</Menu-item>-->
  37 + <!--</Menu>-->
  38 + <!--<br><br>-->
  39 + <!--<Menu mode="horizontal" theme="primary" active-key="1">-->
  40 + <!--<Menu-item key="1">-->
  41 + <!--<Icon type="ionic"></Icon>-->
  42 + <!--<span>导航一</span>-->
  43 + <!--</Menu-item>-->
  44 + <!--<Menu-item key="2">导航二</Menu-item>-->
  45 + <!--<Submenu key="3">-->
  46 + <!--<span slot="title">导航三</span>-->
  47 + <!--<Menu-item key="3-1">导航三 - 一</Menu-item>-->
  48 + <!--<Menu-item key="3-2">导航三 - 二</Menu-item>-->
  49 + <!--<Menu-item key="3-3">导航三 - 三</Menu-item>-->
  50 + <!--</Submenu>-->
  51 + <!--<Menu-item key="4">导航四</Menu-item>-->
  52 + <!--</Menu>-->
  53 + </div>
  54 +</template>
  55 +<script>
  56 + export default {
  57 + props: {},
  58 + data () {
  59 + return {
  60 + mode: 'horizontal'
  61 + }
  62 + },
  63 + computed: {},
  64 + methods: {
  65 + toggleMode () {
  66 + this.mode = this.mode === 'horizontal' ? 'vertical' : 'horizontal';
  67 + }
  68 + }
  69 + }
  70 +</script>
0 71 \ No newline at end of file
... ...
test/routers/select.vue
1 1 <template>
2   - <Row style="margin: 100px">
3   - <i-col span="12" style="padding-right:10px">
4   - <i-select :model.sync="model11" filterable>
5   - <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>
6   - </i-select>
7   - </i-col>
8   - <i-col span="12">
9   - <i-select :model.sync="model12" filterable multiple>
10   - <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>
11   - </i-select>
12   - </i-col>
13   - </Row>
  2 + <i-button @click="model8 = ''">clear</i-button>
  3 + <i-select :model.sync="model8" clearable style="width:200px">
  4 + <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>
  5 + </i-select>
14 6 </template>
15 7 <script>
16 8 export default {
... ... @@ -42,8 +34,7 @@
42 34 label: '重庆市'
43 35 }
44 36 ],
45   - model11: '',
46   - model12: []
  37 + model8: ''
47 38 }
48 39 }
49 40 }
... ...