Prechádzať zdrojové kódy

Dropdown Reconstruction

baiyaaaaa 8 rokov pred
rodič
commit
cf3e15eab9

+ 1 - 0
components.json

@@ -4,6 +4,7 @@
   "dialog": "./packages/dialog/index.js",
   "autocomplete": "./packages/autocomplete/index.js",
   "dropdown": "./packages/dropdown/index.js",
+  "dropdown-menu": "./packages/dropdown-menu/index.js",
   "dropdown-item": "./packages/dropdown-item/index.js",
   "menu": "./packages/menu/index.js",
   "submenu": "./packages/submenu/index.js",

+ 93 - 60
examples/docs/zh-cn/dropdown.md

@@ -3,23 +3,31 @@
     .el-dropdown {
       vertical-align: top;
 
-      & .el-button-group {
-        margin-bottom: 0;
-      }
       & + .el-dropdown {
         margin-left: 15px;
       }
     }
+    .el-dropdown-link {
+      cursor: pointer;
+      color: #20a0ff;
+    }
+    .el-icon-caret-bottom {
+      vertical-align: middle;
+      font-size: 12px;
+    }
   }
 
-  .demo-dropdown .block {
-    display: inline-block;
-    padding: 30px 0;
-    text-align: center;
-    border-right: solid 1px #EFF2F6;
-    flex: 1;
-    &:last-child {
-      border-right: none;
+  .block-col-2 {
+    margin: -24px;
+
+    .el-col {
+      padding: 30px 0;
+      text-align: center;
+      border-right: 1px solid #eff2f6;
+
+      &:last-child {
+        border-right: 0;
+      }
     }
   }
 
@@ -34,17 +42,9 @@
 <script>
   export default {
     methods: {
-      handleMainClick() {
-        alert('click main button');
+      handleClick() {
+        alert('button click');
       }
-    },
-    mounted() {
-      this.$nextTick(() => {
-        let demos = document.querySelectorAll('.source');
-        let lastDemo = demos[demos.length - 1];
-        lastDemo.style.padding = '0';
-        lastDemo.style.display = 'flex';
-      });
     }
   }
 </script>
@@ -59,12 +59,17 @@
 :::demo 通过`text`属性来设置按钮文字。默认条件下,他由一个主要按钮和一个下拉按钮组成,`el-dropdown`中的主要按钮同样可以设置点击事件,只要使用`mainclick`事件即可。默认情况下,下拉按钮只要`hover`即可,无需点击也会显示下拉菜单。
 
 ```html
-<el-dropdown text="下拉菜单" type="text" :icon-separate="false" @mainclick="handleMainClick()">
-  <el-dropdown-item>黄金糕</el-dropdown-item>
-  <el-dropdown-item>狮子头</el-dropdown-item>
-  <el-dropdown-item>螺蛳粉</el-dropdown-item>
-  <el-dropdown-item>双皮奶</el-dropdown-item>
-  <el-dropdown-item>蚵仔煎</el-dropdown-item>
+<el-dropdown>
+  <span class="el-dropdown-link">
+    下拉菜单<i class="el-icon-caret-bottom el-icon-right"></i>
+  </span>
+  <el-dropdown-menu slot="dropdown">
+    <el-dropdown-item>黄金糕</el-dropdown-item>
+    <el-dropdown-item>狮子头</el-dropdown-item>
+    <el-dropdown-item>螺蛳粉</el-dropdown-item>
+    <el-dropdown-item>双皮奶</el-dropdown-item>
+    <el-dropdown-item>蚵仔煎</el-dropdown-item>
+  </el-dropdown-menu>
 </el-dropdown>
 ```
 :::
@@ -76,19 +81,29 @@
 :::demo 设置`icon-separate`属性来呈现不带独立按钮的下拉菜单,设置为`false`即可。在选项三和选项四中插入了一条分割线,只需要在选项四中设置`class`为`divider`。
 
 ```html
-<el-dropdown text="更多菜单" type="primary" :icon-separate="false">
-  <el-dropdown-item>选项一</el-dropdown-item>
-  <el-dropdown-item>选项二</el-dropdown-item>
-  <el-dropdown-item>选项三</el-dropdown-item>
-  <el-dropdown-item class="divider">选项四</el-dropdown-item>
+<el-dropdown>
+  <el-button type="primary">
+    更多菜单<i class="el-icon-caret-bottom el-icon-right"></i>
+  </el-button>
+  <el-dropdown-menu slot="dropdown">
+    <el-dropdown-item>黄金糕</el-dropdown-item>
+    <el-dropdown-item>狮子头</el-dropdown-item>
+    <el-dropdown-item>螺蛳粉</el-dropdown-item>
+    <el-dropdown-item>双皮奶</el-dropdown-item>
+    <el-dropdown-item>蚵仔煎</el-dropdown-item>
+  </el-dropdown-menu>
 </el-dropdown>
-
-<el-dropdown text="主要按钮" type="primary" @mainclick="handleMainClick()">
-  <el-dropdown-item>选项一</el-dropdown-item>
-  <el-dropdown-item>选项二</el-dropdown-item>
-  <el-dropdown-item>选项三</el-dropdown-item>
-  <el-dropdown-item>选项四</el-dropdown-item>
+<el-dropdown split-button type="primary" @click="handleClick">
+  更多菜单
+  <el-dropdown-menu slot="dropdown">
+    <el-dropdown-item>黄金糕</el-dropdown-item>
+    <el-dropdown-item>狮子头</el-dropdown-item>
+    <el-dropdown-item>螺蛳粉</el-dropdown-item>
+    <el-dropdown-item>双皮奶</el-dropdown-item>
+    <el-dropdown-item>蚵仔煎</el-dropdown-item>
+  </el-dropdown-menu>
 </el-dropdown>
+
 ```
 :::
 
@@ -98,33 +113,51 @@
 
 :::demo 在`trigger`属性设置为`click`即可。
 ```html
-<div class="block">
-  <span class="demonstration">hover 激活</span>
-  <el-dropdown text="下拉菜单" type="text" :icon-separate="false" trigger="hover">
-    <el-dropdown-item>选项一</el-dropdown-item>
-    <el-dropdown-item>选项二</el-dropdown-item>
-    <el-dropdown-item>选项三</el-dropdown-item>
-    <el-dropdown-item>选项四</el-dropdown-item>
-  </el-dropdown>
-</div>
-<div class="block">
-  <span class="demonstration">click 激活</span>
-  <el-dropdown text="下拉菜单" type="text" :icon-separate="false" trigger="click">
-    <el-dropdown-item>选项一</el-dropdown-item>
-    <el-dropdown-item>选项二</el-dropdown-item>
-    <el-dropdown-item>选项三</el-dropdown-item>
-    <el-dropdown-item class="divider">选项四</el-dropdown-item>
-  </el-dropdown>
-</div>
+<el-row class="block-col-2">
+  <el-col :span="12">
+    <span class="demonstration">hover 激活</span>
+    <el-dropdown>
+      <span class="el-dropdown-link">
+        下拉菜单<i class="el-icon-caret-bottom el-icon-right"></i>
+      </span>
+      <el-dropdown-menu slot="dropdown">
+        <el-dropdown-item>黄金糕</el-dropdown-item>
+        <el-dropdown-item>狮子头</el-dropdown-item>
+        <el-dropdown-item>螺蛳粉</el-dropdown-item>
+        <el-dropdown-item>双皮奶</el-dropdown-item>
+        <el-dropdown-item>蚵仔煎</el-dropdown-item>
+      </el-dropdown-menu>
+    </el-dropdown>
+  </el-col>
+  <el-col :span="12">
+    <span class="demonstration">click 激活</span>
+    <el-dropdown trigger="click">
+      <span class="el-dropdown-link">
+        下拉菜单<i class="el-icon-caret-bottom el-icon-right"></i>
+      </span>
+      <el-dropdown-menu slot="dropdown">
+        <el-dropdown-item>黄金糕</el-dropdown-item>
+        <el-dropdown-item>狮子头</el-dropdown-item>
+        <el-dropdown-item>螺蛳粉</el-dropdown-item>
+        <el-dropdown-item>双皮奶</el-dropdown-item>
+        <el-dropdown-item>蚵仔煎</el-dropdown-item>
+      </el-dropdown-menu>
+    </el-dropdown>
+  </el-col>
+</el-row>
 ```
 :::
 
+
 ### Attributes
 | 参数          | 说明            | 类型            | 可选值                 | 默认值   |
 |-------------  |---------------- |---------------- |---------------------- |-------- |
-| text          | 菜单按钮文本      | string          |          —             |    —     |
 | type          | 菜单按钮类型,同 Button 组件   | string  |          —             |    —     |
-| trigger       | 触发下拉菜单的方式    | string  |    hover,click  |  hover |
-| icon-separate | 独立的下拉菜单按钮 | boolean         |     —       | true   |
-| size          | 菜单按钮尺寸,同 Button 组件     | string          | large, small, mini  |  —  |
+| split-button  | 带下拉框的按钮    | boolean  |    —  |  false |
 | menu-align    | 菜单水平对齐方向     | string          | start, end  | end |
+| trigger       | 触发下拉的行为     | string          | hover, click  | hover |
+
+### Events
+| 事件名称      | 说明    | 回调参数      |
+|---------- |-------- |---------- |
+| click  | `split-button` 为 true 时,点击左侧按钮的回调 | — |

+ 7 - 0
packages/dropdown-menu/index.js

@@ -0,0 +1,7 @@
+const ElDropdownMenu = require('../dropdown/src/dropdown-menu');
+
+ElDropdownMenu.install = function(Vue) {
+  Vue.component(ElDropdownMenu.name, ElDropdownMenu);
+};
+
+module.exports = ElDropdownMenu;

+ 6 - 8
packages/dropdown/src/dropdown-menu.vue

@@ -1,5 +1,5 @@
 <template>
-  <ul class="el-dropdown__menu" transition="md-fade-bottom">
+  <ul class="el-dropdown__menu">
     <slot></slot>
   </ul>
 </template>
@@ -7,6 +7,11 @@
   import Popper from 'main/utils/popper';
 
   export default {
+    name: 'ElDropdownMenu',
+
+    props: {
+      visible: Boolean
+    },
     data() {
       return {
         popper: null
@@ -17,13 +22,6 @@
         return this.$parent.menuAlign;
       }
     },
-    methods: {
-      updatePopper() {
-        if (this.popper) {
-          this.popper.update();
-        }
-      }
-    },
     mounted() {
       document.body.appendChild(this.$el);
 

+ 61 - 71
packages/dropdown/src/dropdown.vue

@@ -1,78 +1,24 @@
-<template>
-  <div class="el-dropdown"
-    :class="{'el-dropdown--text': type === 'text'}"
-    v-clickoutside="hide"
-  >
-    <!-- 分割的下拉按钮 -->
-    <el-button-group v-if="iconSeparate">
-      <el-button :size="size" :type="type" @click.native="$emit('mainclick')">{{text}}</el-button>
-      <el-button
-        :size="size"
-        :type="type"
-        class="el-dropdown__icon-button"
-        @mouseenter.native="handleMouseEnter"
-        @mouseleave.native="handleMouseLeave"
-        @click.native="handleClick">
-        <i class="el-dropdown__icon el-icon-caret-bottom"></i>
-      </el-button>
-    </el-button-group>
-    <!-- 不分割的下拉按钮 -->
-    <el-button :size="size" :type="type" @mouseenter.native="handleMouseEnter" @mouseleave.native="handleMouseLeave" @click.native="handleClick" v-else>
-      {{text}}<i class="el-dropdown__icon el-icon-caret-bottom"></i>
-    </el-button>
-    <!-- 下拉菜单 -->
-    <transition name="md-fade-bottom">
-      <el-dropdown-menu
-        v-if="visible"
-        @mouseenter.native="handleMouseEnter"
-        @mouseleave.native="handleMouseLeave">
-        <slot></slot>
-      </el-dropdown-menu>
-    </transition>
-  </div>
-</template>
 <script>
-  /**
-   * dropdown
-   * @module packages/dropdown
-   * @desc 下拉菜单组件
-   * @param {string} label - 名称
-   */
-  import ElButton from 'packages/button/index.js';
-  import ElButtonGroup from 'packages/button-group/index.js';
-  import ElDropdownMenu from './dropdown-menu.vue';
   import Clickoutside from 'main/utils/clickoutside';
 
   export default {
     name: 'ElDropdown',
 
-    components: {
-      ElButton,
-      ElButtonGroup,
-      ElDropdownMenu
-    },
-
     directives: { Clickoutside },
 
     props: {
-      text: String,
-      type: String,
-      iconSeparate: {
-        type: Boolean,
-        default: true
-      },
       trigger: {
         type: String,
         default: 'hover'
       },
-      size: {
-        type: String,
-        default: ''
-      },
       menuAlign: {
         type: String,
         default: 'end'
-      }
+      },
+      type: {
+        type: String
+      },
+      splitButton: Boolean
     },
 
     data() {
@@ -82,6 +28,10 @@
       };
     },
 
+    mounted() {
+      this.initEvent();
+    },
+
     methods: {
       show() {
         clearTimeout(this.timeout);
@@ -95,21 +45,61 @@
           this.visible = false;
         }, 150);
       },
-      handleMouseEnter() {
-        if (this.trigger === 'hover') {
-          this.show();
-        }
-      },
-      handleMouseLeave() {
-        if (this.trigger === 'hover') {
-          this.hide();
-        }
-      },
       handleClick() {
-        if (this.trigger === 'click') {
-          this.visible = !this.visible;
+        this.visible = !this.visible;
+      },
+      initEvent() {
+        let { trigger, show, hide, handleClick, splitButton } = this;
+        let triggerElm = splitButton
+          ? this.$refs.trigger.$el
+          : this.$slots.default[0].elm;
+
+        if (trigger === 'hover') {
+          triggerElm.addEventListener('mouseenter', show);
+          triggerElm.addEventListener('mouseleave', hide);
+
+          let dropdown = this.$slots.dropdown[0];
+          let insertHook = dropdown.data.hook.insert;
+          dropdown.data.hook.insert = (vnode) => {
+            insertHook(vnode);
+            this.$nextTick(_ => {
+              vnode.elm.addEventListener('mouseenter', show);
+              vnode.elm.addEventListener('mouseleave', hide);
+            });
+          };
+        } else if (trigger === 'click') {
+          triggerElm.addEventListener('click', handleClick);
         }
       }
+    },
+
+    render(h) {
+      let { hide, splitButton, visible, type } = this;
+      let dropdownElm = visible ? this.$slots.dropdown : null;
+
+      var handleClick = _ => {
+        this.$emit('click');
+      };
+
+      let triggerElm = !splitButton
+        ? this.$slots.default
+        : (<el-button-group>
+            <el-button type={type} nativeOn-click={handleClick}>
+              {this.$slots.default}
+            </el-button>
+            <el-button ref="trigger" type={type} class="el-dropdown__icon-button">
+              <i class="el-dropdown__icon el-icon-caret-bottom"></i>
+            </el-button>
+          </el-button-group>);
+
+      return (
+        <div class="el-dropdown" v-clickoutside={hide}>
+          {triggerElm}
+          <transition name="md-fade-bottom">
+            {dropdownElm}
+          </transition>
+        </div>
+      );
     }
   };
 </script>

+ 0 - 9
packages/theme-default/src/button.css

@@ -35,16 +35,7 @@
       border: 0;
     }
 
-    & .el-icon-right {
-      margin-left: 5px;
-    }
-    & .el-icon-left {
-      margin-right: 5px;
-    }
-
     & [class*="el-icon-"] {
-      /*line-height: 0.9;*/
-      
       & + span {
         margin-left: 5px;
       }

+ 3 - 2
packages/theme-default/src/dropdown.css

@@ -53,8 +53,9 @@
       }
     }
     @e icon {
-      padding-left: 5px;
-      transform: scale(.8, .8);
+      font-size: 12px;
+      vertical-align: middle;
+      margin: 0 3px;
     }
     @m text {
       .el-button-text {

+ 7 - 0
packages/theme-default/src/icon.css

@@ -69,6 +69,13 @@
   animation: rotating 1s linear infinite;
 }
 
+.el-icon-right {
+  margin-left: 5px;
+}
+.el-icon-left {
+  margin-right: 5px;
+}
+
 @keyframes rotating {
   0% {
     transform: rotateZ(0deg);

+ 3 - 0
src/index.js

@@ -3,6 +3,7 @@ import Pagination from '../packages/pagination/index.js';
 import Dialog from '../packages/dialog/index.js';
 import Autocomplete from '../packages/autocomplete/index.js';
 import Dropdown from '../packages/dropdown/index.js';
+import DropdownMenu from '../packages/dropdown-menu/index.js';
 import DropdownItem from '../packages/dropdown-item/index.js';
 import Menu from '../packages/menu/index.js';
 import Submenu from '../packages/submenu/index.js';
@@ -62,6 +63,7 @@ const install = function(Vue) {
   Vue.component(Dialog.name, Dialog);
   Vue.component(Autocomplete.name, Autocomplete);
   Vue.component(Dropdown.name, Dropdown);
+  Vue.component(DropdownMenu.name, DropdownMenu);
   Vue.component(DropdownItem.name, DropdownItem);
   Vue.component(Menu.name, Menu);
   Vue.component(Submenu.name, Submenu);
@@ -133,6 +135,7 @@ module.exports = {
   Dialog,
   Autocomplete,
   Dropdown,
+  DropdownMenu,
   DropdownItem,
   Menu,
   Submenu,