欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue實(shí)現(xiàn)typeahead組件功能(非??孔V)

 更新時(shí)間:2017年08月26日 16:18:42   作者:crper  
本文給大家分享通過(guò)Vue寫一個(gè)挺靠譜的typeahead組件功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧

 前言

之前那個(gè)typeahead寫的太早,不滿足當(dāng)前的業(yè)務(wù)需求。

而且有些瑕疵,還有也不方便傳入數(shù)據(jù)和響應(yīng)數(shù)據(jù)..

于是就推倒了重來(lái),寫了個(gè)V2的版本

看圖,多了一些細(xì)節(jié)的考慮;精簡(jiǎn)了實(shí)現(xiàn)的邏輯代碼

效果圖

這里寫圖片描述

實(shí)現(xiàn)的功能

1: 鼠標(biāo)點(diǎn)擊下拉框之外的區(qū)域關(guān)閉下拉框

2: 支持鍵盤上下鍵選擇,支持鼠標(biāo)選擇

3: 支持列表過(guò)濾搜索

4: 支持外部傳入列表JSON格式的映射

5: 支持placeholder的傳入

6: 選中對(duì)象的響應(yīng)(.sync vue2.3的組件通訊的語(yǔ)法糖)

7: 箭頭icon的映射,感覺(jué)作用不大,移除了

用法

<select-search 
style="max-width:195px" 
placeholder="請(qǐng)選擇廣告主" 
:asyncData.sync="adHostData" 
:mapData="adHostDataList" 
:mapDataFormat="{label:'userName',value:'userId'}">
</select-search>
  • asyncData:響應(yīng)的數(shù)據(jù),也就是選中的..回來(lái)是一個(gè)對(duì)象
  • mapData : 搜索的列表數(shù)據(jù),肯定是外部傳入了…
  • mapData : 列表值映射

代碼

selectSearch.vue

<template>
 <div class="select-search" v-if="typeaheadData" ref="selectSearch" @click.native="showHideMenu($event)">
  <div class="select-header">
   <input type="text" autocomplete="off" readonly :placeholder="placeholder" :value="placeholderValue" @keydown.down.prevent="selectChildWidthArrowDown" @keydown.up.prevent="selectChildWidthArrowUp" @keydown.enter="selectChildWidthEnter">
   <i class="fzicon " :class="isExpand?'fz-ad-jiantou1':'fz-ad-jiantou'"></i>
  </div>
  <div class="select-body" v-if="isExpand && typeaheadData">
   <input type="text" placeholder="關(guān)鍵字" v-model="searchVal" autocomplete="off" @keydown.esc="resetDefaultStatus" @keydown.down.prevent="selectChildWidthArrowDown" @keydown.up.prevent="selectChildWidthArrowUp" @keydown.enter="selectChildWidthEnter">
   <transition name="el-fade-in-linear" mode="out-in">
    <div class="typeahead-filter">
     <transition-group tag="ul" name="el-fade-in-linear" v-show="typeaheadData.length>0">
      <li v-for="(item,index) in typeaheadData" :key="index" :class="item.active ? 'active':''" @mouseenter="setActiveClass(index)" @mouseleave="setActiveClass(index)" @click="selectChild(index)">
       <a href="javascript:;" rel="external nofollow" >
        {{item[mapDataFormat.label]}}
       </a>
      </li>
     </transition-group>
     <p class="noFound" v-show="typeaheadData && typeaheadData.length === 0">未能查詢到,請(qǐng)重新輸入!</p>
    </div>
   </transition>
  </div>
 </div>
</template>
<script>
 export default {
  name: 'selectSearch',
  data: function () {
   return {
    placeholderValue: '',// 給看到選擇內(nèi)容的
    isExpand: false,
    searchVal: '', // 搜索關(guān)鍵字
    resultVal: '', // 保存搜索到的值
    searchList: [], //保存過(guò)濾的結(jié)果集
    currentIndex: -1, // 當(dāng)前默認(rèn)選中的index,
   }
  },
  computed: {
   mapFormatData () { // 外部有傳入格式的時(shí)候映射mapData
    return this.mapData.map(item => {
     item[this.mapDataFormat.value] = item[this.mapDataFormat.value];
     return item;
    });
   },
   typeaheadData () {
    let temp = [];
    if (this.searchVal && this.searchVal === '') {
     return this.mapFormatData;
    } else {
     this.currentIndex = -1; // 重置特殊情況下的索引
     this.mapFormatData.map(item => {
      if (item[this.mapDataFormat.label].indexOf(this.searchVal.toLowerCase().trim()) !== -1) {
       temp.push(item)
      }
      return item;
     })
     return temp;
    }
   }
  },
  props: {
   placeholder: {
    type: String,
    default: '--請(qǐng)選擇--'
   },
   emptyText: {
    type: String,
    default: '暫無(wú)數(shù)據(jù)'
   },
   mapData: { // 外部傳入的列表數(shù)據(jù)
    type: Array,
    default: function () {
     return []
    }
   },
   mapDataFormat: { // 映射傳入數(shù)據(jù)的格式
    type: Object,
    default: function () {
     return {
      label: 'text',
      value: 'value',
      extraText: 'extraText'
     }
    }
   },
   asyncData: { // 實(shí)時(shí)響應(yīng)的值
    type: [Object, String],
    default: function () {
     return {}
    }
   }
  },
  methods: {
   showHideMenu (e) { // 點(diǎn)擊其他區(qū)域關(guān)閉下拉列表
    if (e) {
     if (this.$refs.selectSearch && this.$refs.selectSearch.contains(e.target)) {
      this.isExpand = true;
     } else {
      this.isExpand = false;
     }
    }
   },
   resetDefaultStatus () { // 清除所有選中狀態(tài)
    this.searchVal = '';
    this.currentIndex = -1;
    this.typeaheadData.map(item => {
     this.$delete(item, 'active');
    })
   },
   setActiveClass (index) { // 設(shè)置樣式活動(dòng)類
    this.typeaheadData.map((item, innerIndex) => {
     if (index === innerIndex) {
      this.$set(item, 'active', true);
      this.currentIndex = index; // 這句話是用來(lái)修正index,就是鍵盤上下鍵的索引,不然會(huì)跳位
     } else {
      this.$set(item, 'active', false)
     }
    })
   },
   selectChildWidthArrowDown () {
    // 判斷index選中子項(xiàng)
    if (this.currentIndex < this.typeaheadData.length) {
     this.currentIndex++;
     this.typeaheadData.map((item, index) => {
      this.currentIndex === index ? this.$set(item, 'active', true) : this.$set(item, 'active', false);
     })
    }
   },
   selectChildWidthArrowUp () {
    // 判斷index選中子項(xiàng)
    if (this.currentIndex > 0) {
     this.currentIndex--;
     this.typeaheadData.map((item, index) => {
      this.currentIndex === index ? this.$set(item, 'active', true) : this.$set(item, 'active', false);
     })
    }
   },
   selectChildWidthEnter () {
    // 若是結(jié)果集只有一個(gè),則默認(rèn)選中
    if (this.typeaheadData.length === 1) {
     this.$emit('update:asyncData', this.typeaheadData[0]); // emit響應(yīng)的值
     this.placeholderValue = this.typeaheadData[0][this.mapDataFormat.label];
    } else {
     // 若是搜索的內(nèi)容完全匹配到項(xiàng)內(nèi)的內(nèi)容,則默認(rèn)選中
     this.typeaheadData.map(item => {
      if (this.searchVal === item[this.mapDataFormat.label] || item.active === true) {
       this.$emit('update:asyncData', item); // emit響應(yīng)的值
       this.placeholderValue = item[this.mapDataFormat.label];
      }
     })
    }
    this.isExpand = false;
   },
   selectChild (index) {
    // 鼠標(biāo)點(diǎn)擊選擇子項(xiàng)
    this.typeaheadData.map((item, innerIndex) => {
     if (index === innerIndex || item.active) {
      this.placeholderValue = item[this.mapDataFormat.label];
      this.$emit('update:asyncData', item); // emit響應(yīng)的值
     }
    });
    this.isExpand = false;
   },
  },
  mounted () {
   window.addEventListener('click', this.showHideMenu);
  },
  beforeDestroy () {
   window.removeEventListener('click', this.showHideMenu);
  },
  watch: {
   'isExpand' (newValue) {
    if (newValue === false) {
     this.resetDefaultStatus();
    }
   }
  }
 }
</script>
<style scoped lang="scss">
 .el-fade-in-linear-enter-active,
 .el-fade-in-linear-leave-active,
 .fade-in-linear-enter-active,
 .fade-in-linear-leave-active {
  transition: opacity .2s linear;
 }
 .el-fade-in-enter,
 .el-fade-in-leave-active,
 .el-fade-in-linear-enter,
 .el-fade-in-linear-leave,
 .el-fade-in-linear-leave-active,
 .fade-in-linear-enter,
 .fade-in-linear-leave,
 .fade-in-linear-leave-active {
  opacity: 0;
 }
 .noFound {
  text-align: center;
 }
 .select-search {
  position: relative;
  z-index: 1000;
  a {
   color: #333;
   text-decoration: none;
   padding: 5px;
  }
  ul {
   list-style: none;
   padding: 6px 0;
   margin: 0;
   max-height: 200px;
   overflow-x: hidden;
   overflow-y: auto;
   li {
    display: block;
    width: 100%;
    padding: 5px;
    font-size: 14px;
    padding: 8px 10px;
    position: relative;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #48576a;
    height: 36px;
    line-height: 1.5;
    box-sizing: border-box;
    cursor: pointer;
    &.active {
     background-color: #20a0ff;
     a {
      color: #fff;
     }
    }
   }
  }
  .select-header {
   position: relative;
   border-radius: 4px;
   border: 1px solid #bfcbd9;
   outline: 0;
   padding: 0 8px;
   >input {
    border: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    outline: 0;
    box-sizing: border-box;
    color: #1f2d3d;
    font-size: inherit;
    height: 36px;
    line-height: 1;
   }
   >i {
    transition: all .3s linear;
    display: inline-block;
    position: absolute;
    right: 3%;
    top: 50%;
    transform: translateY(-50%);
   }
  }
  .select-body {
   position: absolute;
   border-radius: 2px;
   background-color: #fff;
   box-sizing: border-box;
   margin: 5px 0;
   padding: 8px;
   width: 100%;
   box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
   >input {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-color: #fff;
    background-image: none;
    border-radius: 4px;
    border: 1px solid #bfcbd9;
    box-sizing: border-box;
    color: #1f2d3d;
    font-size: inherit;
    height: 36px;
    line-height: 1;
    outline: 0;
    padding: 3px 10px;
    transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
    width: 100%;
    display: inline-block;
    &:focus {
     outline: 0;
     border-color: #20a0ff;
    }
   }
  }
 }
</style>

總結(jié)

以上所述是小編給大家介紹的Vue實(shí)現(xiàn)typeahead組件功能(非??孔V),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 如何解決element-ui中多個(gè)table在tab切換時(shí)出現(xiàn)寬度縮小問(wèn)題

    如何解決element-ui中多個(gè)table在tab切換時(shí)出現(xiàn)寬度縮小問(wèn)題

    這篇文章主要介紹了如何解決element-ui中多個(gè)table在tab切換時(shí)出現(xiàn)寬度縮小問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 關(guān)于element?ui?表格中的常見特殊屬性說(shuō)明

    關(guān)于element?ui?表格中的常見特殊屬性說(shuō)明

    這篇文章主要介紹了關(guān)于element?ui?表格中的常見特殊屬性說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • vue3項(xiàng)目目錄結(jié)構(gòu)示例詳解

    vue3項(xiàng)目目錄結(jié)構(gòu)示例詳解

    更好的了解項(xiàng)目的目錄結(jié)構(gòu),能更好的去開發(fā)項(xiàng)目,下面這篇文章主要給大家介紹了關(guān)于vue3項(xiàng)目目錄結(jié)構(gòu)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • vue項(xiàng)目nginx二級(jí)域名配置方式

    vue項(xiàng)目nginx二級(jí)域名配置方式

    這篇文章主要介紹了vue項(xiàng)目nginx二級(jí)域名配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 詳解Vue2.0組件的繼承與擴(kuò)展

    詳解Vue2.0組件的繼承與擴(kuò)展

    這篇文章主要介紹了詳解Vue2.0組件的繼承與擴(kuò)展,主要分享slot、mixins/extends和extend的用法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • vue的axios和mock.js你了解嗎

    vue的axios和mock.js你了解嗎

    這篇文章主要為大家詳細(xì)介紹了vue的axios和mock.js,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • vue腳手架及vue-router基本使用

    vue腳手架及vue-router基本使用

    這篇文章主要介紹了vue腳手架及vue-router基本使用,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-04-04
  • vue3?keepalive源碼解析解決線上問(wèn)題

    vue3?keepalive源碼解析解決線上問(wèn)題

    這篇文章主要為大家講解了vue3?keepalive源碼解析解決線上問(wèn)題,需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • vue中使用elementUI組件手動(dòng)上傳圖片功能

    vue中使用elementUI組件手動(dòng)上傳圖片功能

    Vue是一套構(gòu)建用戶界面的框架, 開發(fā)只需要關(guān)注視圖層, 它不僅易于上手,還便于與第三方庫(kù)或既有項(xiàng)目的整合。這篇文章主要介紹了vue中使用elementUI組件手動(dòng)上傳圖片,需要的朋友可以參考下
    2019-12-12
  • 基于Vue uniapp實(shí)現(xiàn)貪吃蛇游戲

    基于Vue uniapp實(shí)現(xiàn)貪吃蛇游戲

    貪吃蛇游戲想必是很多70、80后的回憶,一直到現(xiàn)在也深受大家的喜歡。本文將利用Vue+uniapp實(shí)現(xiàn)這一經(jīng)典的游戲,感興趣的可以了解一下
    2022-04-04

最新評(píng)論