1. 程式人生 > 其它 >element原始碼解析(2) -- autocomplete

element原始碼解析(2) -- autocomplete

技術標籤:element ui

autocomplete原始碼解析


autocomplete中包含三個元件,input和suggestion/el-scrollbar

在這裡插入圖片描述
在這裡插入圖片描述

template

一個class:

el-autocomplete:相對定位和行內塊;
一個自定義指令:v-clickoutside:點選此dom元素外觸發事件

el-input

四個emit觸發事件:input,focus,blur,clear調節顯示隱藏高亮清除
四個鍵盤事件up,down,enter,tab
四個插槽:prepend,append,prefix,suffix
v-bind="[$props, $attrs]",v-bind可用陣列/物件,說明接收所有跟input相關的屬性

el-autocomplete-suggestions

visible-arrow:沒見到這個屬性發揮作用

四個屬性:

:popper-options=“popperOptions”
預設無
:append-to-body=“popperAppendToBody”

預設插入到body

popperAppendToBody: {
        type: Boolean,
        default: true
      },

:placement=“placement”:
預設正下方

 placement: {
        type: String,
        default: 'bottom-start'
      },

:id=“id”
生成id隨機數

export const generateId = function(){
  return Math.floor(Math.random() * 10000)
}

popperClass:

屬於自定義autocomplete-suggestions的class

script

引入防抖函式,外部點選指令,
混入廣播派發事件,獲取焦點方法Focus(‘input’)
Migrating 生產中沒有用處,開發中可以給提示警告

  import debounce from 'throttle-debounce/debounce';
  import Clickoutside from 'element-ui/src/utils/clickoutside';
  import Emitter from 'element-ui/src/mixins/emitter';
  import Migrating from 'element-ui/src/mixins/migrating';
  import { generateId } from 'element-ui/src/utils/util';
  import Focus from 'element-ui/src/mixins/focus';

props

24個屬性

  1. valueKey: 預設為value,取list中的key,輸入建議物件中用於顯示的鍵名
  2. popperClass:Autocomplete 下拉列表的類名
  3. popperOptions:暫時沒用上,應該與vue-popper選項有關
  4. placeholoder: 輸入框佔位文字
  5. clearable:是否清除,預設不顯示
  6. disabled:是否禁用,預設不禁用
  7. name:原生屬性,input的name,在v-bind中實現
  8. size:沒見著怎麼用
  9. value:給預設值
  10. maxlength:最大數量
  11. minlength:最小數量
  12. autofocus:是否自動獲取焦點
  13. fetchSuggestions:可以沒有queryString,必須回撥,回撥必須帶引數,引數就是suggestions的結果,用意自然是可以去根據queryString去做過濾,但其實直接傳過濾後的資料不香嗎,繞得不太好.
  14. triggerOnFocus:是否在輸入框focus的時候給出建議列表,預設為true,獲取焦點的時候去判斷
  15. customItem:沒發現用到
  16. selectWhenUnmatched:預設為false,enter的時候觸發,不匹配,清空
  17. prefixIcon:el-input的屬性
  18. suffixIcon:el-input的屬性
  19. label:el-input屬性
  20. debounce:防抖時間
  21. placement:建議列表位置
  22. hideLoading:是否隱藏loading
  23. popperAppendToBody:彈框是否依附於body,預設依附,否則插入
  24. highlightFirstItem:是否預設突出顯示遠端搜尋建議中的第一項
handleFocus(event) {
        this.activated = true;
        this.$emit('focus', event);
        if (this.triggerOnFocus) {
          this.debouncedGetData(this.value);
        }
      },
props: {
      valueKey: {
        type: String,
        default: 'value'
      },
      popperClass: String,
      popperOptions: Object,
      placeholder: String,
      clearable: {
        type: Boolean,
        default: false
      },
      disabled: Boolean,
      name: String,
      size: String,
      value: String,
      maxlength: Number,
      minlength: Number,
      autofocus: Boolean,
      fetchSuggestions: Function,
      triggerOnFocus: {
        type: Boolean,
        default: true
      },
      customItem: String,
      selectWhenUnmatched: {
        type: Boolean,
        default: false
      },
      prefixIcon: String,
      suffixIcon: String,
      label: String,
      debounce: {
        type: Number,
        default: 300
      },
      placement: {
        type: String,
        default: 'bottom-start'
      },
      hideLoading: Boolean,
      popperAppendToBody: {
        type: Boolean,
        default: true
      },
      highlightFirstItem: {
        type: Boolean,
        default: false
      }
    },

data

五個自定義變數
actived表示獲取焦點時為true,啟用搜尋建議
suggestions建議列表的資料
loading預設沒有載入
highlightedIndex:表示高亮的選項
suggestionDisabled:表示禁用

data() {
      return {
        activated: false,
        suggestions: [],
        loading: false,
        highlightedIndex: -1,
        suggestionDisabled: false
      };
    },

computed

計算屬性:
如果資料發生變化,則根據當前判斷是否啟用狀態,根據是否有資料來顯示隱藏:

suggestionVisible() {
  const suggestions = this.suggestions;
  let isValidData = Array.isArray(suggestions) && suggestions.length > 0;
  return (isValidData || this.loading) && this.activated;
},
id() {
   return `el-autocomplete-${generateId()}`;
}

watch

監聽,如果可見性發生變化,直接給子元件派發事件,告訴子元件值和寬度

watch: {
      suggestionVisible(val) {
        let $input = this.getInput();
        if ($input) {
          this.broadcast('ElAutocompleteSuggestions', 'visible', [val, $input.offsetWidth]);
        }
      }
    },

mounted

this.debouncedGetData = debounce(this.debounce, this.getData);
      this.$on('item-click', item => {
        this.select(item);
      });
      let $input = this.getInput();
      $input.setAttribute('role', 'textbox');
      $input.setAttribute('aria-autocomplete', 'list');
      $input.setAttribute('aria-controls', 'id');
      $input.setAttribute('aria-activedescendant', `${this.id}-item-${this.highlightedIndex}`);

methods