Browse Source

autocomplete dropdown use el-scrollbar

baiyaaaaa 8 years ago
parent
commit
9dee785465

+ 1 - 2
examples/docs/en-US/input.md

@@ -120,7 +120,7 @@
       }
     }
   }
-  .el-autocomplete__suggestions.my-autocomplete {
+  .el-autocomplete-suggestion.my-autocomplete {
     li {
       line-height: normal;
       padding: 7px *;
@@ -133,7 +133,6 @@
         font-size: 12px;
         color: #b4b4b4;
       }
-
       .highlighted .addr {
         color: #ddd;
       }

+ 1 - 2
examples/docs/zh-CN/input.md

@@ -161,7 +161,7 @@
       }
     }
   }
-  .el-autocomplete__suggestions.my-autocomplete {
+  .el-autocomplete-suggestion.my-autocomplete {
     li {
       line-height: normal;
       padding: 7px *;
@@ -174,7 +174,6 @@
         font-size: 12px;
         color: #b4b4b4;
       }
-
       .highlighted .addr {
         color: #ddd;
       }

+ 27 - 21
packages/autocomplete/src/autocomplete-suggestions.vue

@@ -1,30 +1,36 @@
 <template>
   <transition name="el-zoom-in-top" @after-leave="doDestroy">
-    <ul
+    <div
       v-show="showPopper"
-      class="el-autocomplete__suggestions"
+      class="el-autocomplete-suggestion"
       :class="{ 'is-loading': parent.loading }"
       :style="{ width: dropdownWidth }"
     >
-      <li v-if="parent.loading"><i class="el-icon-loading"></i></li>
-      <template v-for="(item, index) in suggestions" v-else>
-        <li
-          v-if="!parent.customItem"
-          :class="{'highlighted': parent.highlightedIndex === index}"
-          @click="select(item)"
-        >
-          {{item.value}}
-        </li>
-        <component
-          v-else
-          :class="{'highlighted': parent.highlightedIndex === index}"
-          @click="select(item)"
-          :is="parent.customItem"
-          :item="item"
-          :index="index">
-        </component>
-      </template>
-    </ul>
+      <el-scrollbar
+        tag="ul"
+        wrap-class="el-autocomplete-suggestion__wrap"
+        view-class="el-autocomplete-suggestion__list"
+      >
+        <li v-if="parent.loading"><i class="el-icon-loading"></i></li>
+        <template v-for="(item, index) in suggestions" v-else>
+          <li
+            v-if="!parent.customItem"
+            :class="{'highlighted': parent.highlightedIndex === index}"
+            @click="select(item)"
+          >
+            {{item.value}}
+          </li>
+          <component
+            v-else
+            :class="{'highlighted': parent.highlightedIndex === index}"
+            @click="select(item)"
+            :is="parent.customItem"
+            :item="item"
+            :index="index">
+          </component>
+        </template>
+      </el-scrollbar>
+    </div>
   </transition>
 </template>
 <script>

+ 10 - 10
packages/autocomplete/src/autocomplete.vue

@@ -133,22 +133,22 @@
       },
       highlight(index) {
         if (!this.suggestionVisible || this.loading) { return; }
-        if (index < 0) {
-          index = 0;
-        } else if (index >= this.suggestions.length) {
+        if (index < 0) index = 0;
+        if (index >= this.suggestions.length) {
           index = this.suggestions.length - 1;
         }
-        var elSuggestions = this.$refs.suggestions.$el;
+        const suggestion = this.$refs.suggestions.$el.querySelector('.el-autocomplete-suggestion__wrap');
+        const suggestionList = suggestion.querySelectorAll('.el-autocomplete-suggestion__list li');
 
-        var elSelect = elSuggestions.children[index];
-        var scrollTop = elSuggestions.scrollTop;
-        var offsetTop = elSelect.offsetTop;
+        let highlightItem = suggestionList[index];
+        let scrollTop = suggestion.scrollTop;
+        let offsetTop = highlightItem.offsetTop;
 
-        if (offsetTop + elSelect.scrollHeight > (scrollTop + elSuggestions.clientHeight)) {
-          elSuggestions.scrollTop += elSelect.scrollHeight;
+        if (offsetTop + highlightItem.scrollHeight > (scrollTop + suggestion.clientHeight)) {
+          suggestion.scrollTop += highlightItem.scrollHeight;
         }
         if (offsetTop < scrollTop) {
-          elSuggestions.scrollTop -= elSelect.scrollHeight;
+          suggestion.scrollTop -= highlightItem.scrollHeight;
         }
 
         this.highlightedIndex = index;

+ 54 - 52
packages/theme-default/src/autocomplete.css

@@ -6,71 +6,73 @@
   @b autocomplete {
     position: relative;
     display: inline-block;
+  }
+  @b autocomplete-suggestion {
+    margin: 5px 0 0;
+    box-shadow: 0 0 6px 0 rgba(0,0,0,0.04), 0 2px 4px 0 rgba(0,0,0,0.12);
 
-    @e suggestions {
-      position: absolute;
-      left: 0;
-      top: 110%;
-      margin: 5px 0 0;
+    @e wrap {
+      max-height: 280px;
+      overflow: auto;
       background-color: var(--color-white);
       border: 1px solid var(--color-base-gray);
-      width: 100%;
       padding: 6px 0;
-      z-index: 10;
       border-radius: 2px;
-      max-height: 280px;
       box-sizing: border-box;
-      overflow: auto;
-      box-shadow: 0 0 6px 0 rgba(0,0,0,0.04), 0 2px 4px 0 rgba(0,0,0,0.12);
+    }
 
-      & li {
-        list-style: none;
-        line-height: 36px;
-        padding: 0 10px;
-        margin: 0;
-        cursor: pointer;
-        color: var(--color-extra-light-black);
-        font-size: 14px;
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
+    @e list {
+      margin: 0;
+      padding: 0;
+    }
 
-        &:hover {
-          background-color: var(--select-option-hover-background);
-        }
-        &.highlighted {
-          background-color: var(--color-primary);
-          color: var(--color-white);
-        }
-        &:active {
-          background-color: darken(var(--color-primary), 0.2);
-        }
-        &.divider {
-          margin-top: 6px;
-          border-top: 1px solid var(--color-base-gray);
-        }
-        &.divider:last-child {
-          margin-bottom: -6px;
-        }
+    & li {
+      list-style: none;
+      line-height: 36px;
+      padding: 0 10px;
+      margin: 0;
+      cursor: pointer;
+      color: var(--color-extra-light-black);
+      font-size: 14px;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+
+      &:hover {
+        background-color: var(--select-option-hover-background);
+      }
+      &.highlighted {
+        background-color: var(--color-primary);
+        color: var(--color-white);
+      }
+      &:active {
+        background-color: darken(var(--color-primary), 0.2);
+      }
+      &.divider {
+        margin-top: 6px;
+        border-top: 1px solid var(--color-base-gray);
       }
+      &.divider:last-child {
+        margin-bottom: -6px;
+      }
+    }
 
-      @when loading {
-        li {
-          text-align: center;
-          height: 100px;
-          line-height: 100px;
-          font-size: 20px;
-          color: #999;
-          @utils-vertical-center;
+    @when loading {
+      li {
+        text-align: center;
+        height: 100px;
+        line-height: 100px;
+        font-size: 20px;
+        color: #999;
+        @utils-vertical-center;
 
-          &:hover {
-            background-color: var(--color-white);
-          }
+        &:hover {
+          background-color: var(--color-white);
         }
+      }
 
-        & .el-icon-loading {
-          vertical-align: middle;
-        }
+      & .el-icon-loading {
+        vertical-align: middle;
       }
     }
   }

+ 35 - 45
test/unit/specs/autocomplete.spec.js

@@ -57,7 +57,7 @@ describe('Autocomplete', () => {
     setTimeout(_ => {
       const suggestions = vm.$refs.autocomplete.$refs.suggestions.$el;
       expect(suggestions.style.display).to.not.equal('none');
-      expect(suggestions.children.length).to.be.equal(4);
+      expect(suggestions.querySelectorAll('.el-autocomplete-suggestion__list li').length).to.be.equal(4);
 
       document.body.click();
       setTimeout(_ => {
@@ -74,14 +74,12 @@ describe('Autocomplete', () => {
           ref="autocomplete"
           :fetch-suggestions="querySearch"
           placeholder="请输入内容autocomplete2"
-          @select="handleSelect"
         ></el-autocomplete>
       `,
       data() {
         return {
           restaurants: [],
-          state: '',
-          onceSelected: false
+          state: ''
         };
       },
       methods: {
@@ -102,27 +100,29 @@ describe('Autocomplete', () => {
             { 'value': '新旺角茶餐厅', 'address': '上海市普陀区真北路988号创邑金沙谷6号楼113' },
             { 'value': '泷千家(天山西路店)', 'address': '天山西路438号' }
           ];
-        },
-        handleSelect() {
-          this.onceSelected = true;
         }
       },
       mounted() {
         this.restaurants = this.loadAll();
       }
     }, true);
-    let elm = vm.$el;
-    let inputElm = elm.querySelector('input');
+    const autocomplete = vm.$refs.autocomplete;
+    const elm = vm.$el;
+    const inputElm = elm.querySelector('input');
+    const spy = sinon.spy();
+
+    autocomplete.$on('select', spy);
     inputElm.focus();
 
     setTimeout(_ => {
-      let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
-      suggestionsList.children[1].click();
+      const suggestions = autocomplete.$refs.suggestions.$el;
+      const suggestionList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
+      suggestionList[1].click();
       setTimeout(_ => {
         expect(inputElm.value).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
         expect(vm.state).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
-        expect(vm.onceSelected).to.be.true;
-        expect(elm.querySelector('.el-autocomplete__suggestions')).to.not.exist;
+        expect(spy.withArgs().calledOnce).to.be.true;
+        expect(suggestions.style.display).to.be.equal('none');
         done();
       }, 500);
     }, 500);
@@ -135,14 +135,12 @@ describe('Autocomplete', () => {
           v-model="state"
           :fetch-suggestions="querySearch"
           placeholder="请输入内容autocomplete3"
-          @select="handleSelect"
         ></el-autocomplete>
       `,
       data() {
         return {
           restaurants: [],
-          state: '',
-          onceSelected: false
+          state: ''
         };
       },
       methods: {
@@ -181,28 +179,25 @@ describe('Autocomplete', () => {
             { 'value': '纵食', 'address': '元丰天山花园(东门) 双流路267号' },
             { 'value': '钱记', 'address': '上海市长宁区天山西路' }
           ];
-        },
-        handleSelect() {
-          this.onceSelected = true;
         }
       },
       mounted() {
         this.restaurants = this.loadAll();
       }
     }, true);
-    let elm = vm.$el;
-    let inputElm = elm.querySelector('input');
+    const autocomplete = vm.$refs.autocomplete;
+    const inputElm = autocomplete.$el.querySelector('input');
+
     inputElm.focus();
 
     setTimeout(_ => {
-      vm.$refs.autocomplete.highlight(8);
+      autocomplete.highlight(8);
       vm.$nextTick(_ => {
-        let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
-        let highlightedItem = suggestionsList.children[8];
-        expect(highlightedItem.className).to.be.equal('highlighted');
-        expect(suggestionsList.scrollTop === highlightedItem.scrollHeight).to.be.true;
-
-        vm.$refs.autocomplete.highlight(8);
+        const suggestions = autocomplete.$refs.suggestions.$el.querySelector('.el-autocomplete-suggestion__wrap');
+        let suggestionsList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
+        let highlightedItem = suggestionsList[8];
+        expect(highlightedItem.classList.contains('highlighted')).to.be.true;
+        expect(suggestions.scrollTop === highlightedItem.scrollHeight).to.be.true;
         done();
       });
     }, 500);
@@ -215,14 +210,12 @@ describe('Autocomplete', () => {
           v-model="state"
           :fetch-suggestions="querySearch"
           placeholder="请输入内容autocomplete3"
-          @select="handleSelect"
         ></el-autocomplete>
       `,
       data() {
         return {
           restaurants: [],
-          state: '',
-          onceSelected: false
+          state: ''
         };
       },
       methods: {
@@ -251,29 +244,27 @@ describe('Autocomplete', () => {
             { 'value': '阿姨奶茶/豪大大', 'address': '嘉定区曹安路1611号' },
             { 'value': '新麦甜四季甜品炸鸡', 'address': '嘉定区曹安公路2383弄55号' }
           ];
-        },
-        handleSelect() {
-          this.onceSelected = true;
         }
       },
       mounted() {
         this.restaurants = this.loadAll();
       }
     }, true);
-    let elm = vm.$el;
-    let inputElm = elm.querySelector('input');
+    const autocomplete = vm.$refs.autocomplete;
+    let inputElm = vm.$el.querySelector('input');
     inputElm.focus();
 
     setTimeout(_ => {
-      vm.$refs.autocomplete.highlight(15);
+      autocomplete.highlight(15);
       vm.$nextTick(_ => {
-        let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
-        let highlightedItem = suggestionsList.children[11];
+        const suggestions = autocomplete.$refs.suggestions.$el;
+        const suggestionsList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
+        let highlightedItem = suggestionsList[11];
         expect(highlightedItem.className).to.be.equal('highlighted');
 
-        vm.$refs.autocomplete.highlight(-5);
+        autocomplete.highlight(-5);
         vm.$nextTick(_ => {
-          let highlightedItem = suggestionsList.children[0];
+          let highlightedItem = suggestionsList[0];
           expect(highlightedItem.className).to.be.equal('highlighted');
         });
         done();
@@ -321,13 +312,12 @@ describe('Autocomplete', () => {
         this.restaurants = this.loadAll();
       }
     }, true);
-    let elm = vm.$el;
-    let inputElm = elm.querySelector('input');
+    let inputElm = vm.$el.querySelector('input');
     inputElm.focus();
 
     setTimeout(_ => {
-      let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
-      expect(suggestionsList.style.display).to.be.equal('none');
+      let suggestions = vm.$refs.autocomplete.$refs.suggestions.$el;
+      expect(suggestions.style.display).to.be.equal('none');
       done();
     }, 500);
   });