qingwei.li 8 years ago
parent
commit
547612bf6e

+ 1 - 0
examples/docs/en-US/table.md

@@ -1362,6 +1362,7 @@ Customize table column so it can be integrated with other components.
 | row-key | key of row data, used for optimizing rendering. Required if `reserve-selection` is on | Function(row)/String | — | — |
 | context | context of Table, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context, can be overridden by `context` in `el-table-column` | Object | - | current context where Table lies |
 | empty-text | Displayed text when data is empty. You can customize this area with `slot="empty"` | String | | - | No Data |
+| virtual-scrollbar | Enable virtual scrollbar | Boolean | - | false |
 
 ### Table Events
 | Event Name | Description | Parameters |

+ 1 - 0
examples/docs/zh-CN/table.md

@@ -1369,6 +1369,7 @@
 | row-key | 行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row)/String | — | — |
 | context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root`。优先读取 column 的 context 属性。 | Object | - | Table 所处上下文 |
 | empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | | - | 暂无数据 |
+| virtual-scrollbar | 启用虚拟滚动条 | Boolean | - | false |
 
 ### Table Events
 | 事件名 | 说明 | 参数 |

+ 35 - 19
packages/scrollbar/src/main.js

@@ -1,6 +1,7 @@
 // reference https://github.com/noeldelgado/gemini-scrollbar/blob/master/index.js
 
 import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
+import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
 import * as util from './util';
 import Bar from './bar';
 
@@ -10,6 +11,7 @@ export default {
   components: { Bar },
 
   props: {
+    native: Boolean,
     wrapStyle: {},
     wrapClass: {},
     viewClass: {},
@@ -37,7 +39,7 @@ export default {
   },
 
   render(h) {
-    let gutter = util.getScrollBarWidth();
+    let gutter = scrollbarWidth();
     let style = this.wrapStyle;
 
     if (gutter) {
@@ -50,31 +52,43 @@ export default {
         style += `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;
       }
     }
+    const view = h(this.tag, {
+      class: ['el-scrollbar__view', this.viewClass],
+      style: this.viewStyle,
+      ref: 'resize'
+    }, this.$slots.default);
     const wrap = (
       <div
         ref="wrap"
         style={ style }
         onScroll={ this.handleScroll }
-        class={ [this.wrapClass, 'el-scrollbar__wrap'] }>
-        {
-          h(this.tag, {
-            class: ['el-scrollbar__view', this.viewClass],
-            style: this.viewStyle,
-            ref: 'resize'
-          }, this.$slots.default)
-        }
+        class={ [this.wrapClass, 'el-scrollbar__wrap el-scrollbar__wrap--hidden-default'] }>
+        { [view] }
       </div>
     );
-    const nodes = ([
-      wrap,
-      <Bar
-        move={ this.moveX }
-        size={ this.sizeWidth }></Bar>,
-      <Bar
-        vertical
-        move={ this.moveY }
-        size={ this.sizeHeight }></Bar>
-    ]);
+    let nodes;
+
+    if (!this.native) {
+      nodes = ([
+        wrap,
+        <Bar
+          move={ this.moveX }
+          size={ this.sizeWidth }></Bar>,
+        <Bar
+          vertical
+          move={ this.moveY }
+          size={ this.sizeHeight }></Bar>
+      ]);
+    } else {
+      nodes = ([
+        <div
+          ref="wrap"
+          class={ [this.wrapClass, 'el-scrollbar__wrap'] }
+          style={ style }>
+          { [view] }
+        </div>
+      ]);
+    }
     return h('div', { class: 'el-scrollbar' }, nodes);
   },
 
@@ -99,11 +113,13 @@ export default {
   },
 
   mounted() {
+    if (this.native) return;
     this.$nextTick(this.update);
     !this.noresize && addResizeListener(this.$refs.resize, this.update);
   },
 
   destroyed() {
+    if (this.native) return;
     !this.noresize && removeResizeListener(this.$refs.resize, this.update);
   }
 };

+ 0 - 27
packages/scrollbar/src/util.js

@@ -23,33 +23,6 @@ export const BAR_MAP = {
   }
 };
 
-let scrollBarWidth;
-
-export function getScrollBarWidth() {
-  if (Vue.prototype.$isServer) return 0;
-  if (scrollBarWidth !== undefined) return scrollBarWidth;
-
-  const outer = document.createElement('div');
-  outer.className = 'el-scrollbar__wrap';
-  outer.style.visibility = 'hidden';
-  outer.style.width = '100px';
-  outer.style.position = 'absolute';
-  outer.style.top = '-9999px';
-  document.body.appendChild(outer);
-
-  const widthNoScroll = outer.offsetWidth;
-  outer.style.overflow = 'scroll';
-
-  const inner = document.createElement('div');
-  inner.style.width = '100%';
-  outer.appendChild(inner);
-
-  const widthWithScroll = inner.offsetWidth;
-  outer.parentNode.removeChild(outer);
-
-  return widthNoScroll - widthWithScroll;
-};
-
 export function renderThumbStyle({ move, size, bar }) {
   const style = {};
   const translate = `translate${bar.axis}(${ move }%)`;

+ 3 - 1
packages/table/src/table-layout.js

@@ -1,3 +1,5 @@
+import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
+
 class TableLayout {
   constructor(options) {
     this.table = null;
@@ -17,7 +19,7 @@ class TableLayout {
     this.viewportHeight = null; // Table Height - Scroll Bar Height
     this.bodyHeight = null; // Table Height - Table Header Height
     this.fixedBodyHeight = null; // Table Height - Table Header Height - Scroll Bar Height
-    this.gutterWidth = 0;
+    this.gutterWidth = scrollbarWidth();
 
     for (let name in options) {
       if (options.hasOwnProperty(name)) {

+ 3 - 0
packages/table/src/table.vue

@@ -21,6 +21,7 @@
     <el-scrollbar
       class="el-table__body-wrapper"
       ref="bodyWrapper"
+      :native="!virtualScrollbar"
       :wrap-style="[bodyHeight]">
       <table-body
         :context="context"
@@ -133,6 +134,8 @@
 
       width: [String, Number],
 
+      virtualScrollbar: Boolean,
+
       height: [String, Number],
 
       maxHeight: [String, Number],

+ 5 - 3
packages/theme-default/src/scrollbar.css

@@ -15,9 +15,11 @@
     @e wrap {
       overflow: scroll;
 
-      &::-webkit-scrollbar {
-        width: 0;
-        height: 0;
+      @m hidden-default {
+        &::-webkit-scrollbar {
+          width: 0;
+          height: 0;
+        }
       }
     }
 

+ 7 - 1
src/index.js

@@ -55,6 +55,8 @@ import Card from '../packages/card';
 import Rate from '../packages/rate';
 import Steps from '../packages/steps';
 import Step from '../packages/step';
+import Carousel from '../packages/carousel';
+import Scrollbar from '../packages/scrollbar';
 import locale from 'element-ui/src/locale';
 
 const install = function(Vue, opts = {}) {
@@ -113,6 +115,8 @@ const install = function(Vue, opts = {}) {
   Vue.component(Rate.name, Rate);
   Vue.component(Steps.name, Steps);
   Vue.component(Step.name, Step);
+  Vue.component(Carousel.name, Carousel);
+  Vue.component(Scrollbar.name, Scrollbar);
 
   Vue.use(Loading.directive);
 
@@ -188,5 +192,7 @@ module.exports = {
   Card,
   Rate,
   Steps,
-  Step
+  Step,
+  Carousel,
+  Scrollbar
 };

+ 28 - 0
src/utils/scrollbar-width.js

@@ -0,0 +1,28 @@
+import Vue from 'vue';
+
+let scrollBarWidth;
+
+export default function() {
+  if (Vue.prototype.$isServer) return 0;
+  if (scrollBarWidth !== undefined) return scrollBarWidth;
+
+  const outer = document.createElement('div');
+  outer.className = 'el-scrollbar__wrap';
+  outer.style.visibility = 'hidden';
+  outer.style.width = '100px';
+  outer.style.position = 'absolute';
+  outer.style.top = '-9999px';
+  document.body.appendChild(outer);
+
+  const widthNoScroll = outer.offsetWidth;
+  outer.style.overflow = 'scroll';
+
+  const inner = document.createElement('div');
+  inner.style.width = '100%';
+  outer.appendChild(inner);
+
+  const widthWithScroll = inner.offsetWidth;
+  outer.parentNode.removeChild(outer);
+
+  return widthNoScroll - widthWithScroll;
+};