乐趣区

关于前端:Vue-手写组件之实现一个可显示图片的自定义远程搜索框

在理论的 vue 我的项目开发中,个别与 element-ui 搭配应用的比拟多。

如下图,这个是 element-ui 官网为咱们提供的近程搜寻组件,它可能在咱们输出时,依据输出内容实时从近程服务器获取内容并显示在下拉框中。

当初问题来了,咱们有这样一个需要:下拉列表中不仅仅能展现文字内容,也要显示相应的文字说明图片

Element-ui 列表中对应的内容显然 是搜寻到的内容的 value 字段,是一个字符串,是无奈满足咱们放入图片的需要的。

这时就须要咱们本人去封装一个自定义的能显示图片的近程搜寻框了。

原理其实很简略:

  1. 监听文本框的输出事件,并且为其增加防抖(性能上的优化,使得进行输出一段时间后再去调用搜寻函数)
  2. 将搜寻到的内容放入一个无序列表中,在输入框下方显示
  3. 为列表设置最大高度 (否则将依据搜寻到的内容个数有限向下缩短),超过这个高度则加滚动条
  4. 点击其余区域或者选中某一项时列表框暗藏
  5. 款式,每项加边框,上面加暗影,每项鼠标挪动进入时色彩置灰,移除时复原

最终实现成果如图:

代码如下:

// 封了一个从服务器近程获取搜寻内容的输入框,比 autocompleteuole 多了在列表中显示图片的性能
<template>
  <div class="container">
    <el-input
      placeholder="输出单词或 ID"
      v-model="obj[name]"
      @input="whileInput"
      @blur="isShow=false"
      clearable
      style="width: 200px"
    >
    </el-input>
    <div class="selectLIst" v-if="isShow==true">
      <div v-for="item in cardResult" :key="item.id" @click="handleSelect(item)" class="item">
        <span>{{item.value}}</span>
        ![](item.picUrl)
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'RemoteSearch',
  props: {
    obj: {type: Object},
    name: {type: String},

  },
  data() {
    return {
      timer: null,   // 这里放里面其实不平安,容易被篡改
      cardResult: [],
      isShow: false
    }
  },
  methods: {whileInput() {
      this.isShow = true
      // 防抖
      if(this.timer) {clearTimeout(this.timer)
      }
      this.timer = setTimeout(()=>{this.fetchContent()
      },800)
    },
    async fetchContent() {this.cardResult = []
      let queryObj = {type:1}
      // 判断 queryString 是数字还是单词
      if(!isNaN(Number(this.obj[this.name]))) {queryObj.id = this.obj[this.name]
      } else {queryObj.word = this.obj[this.name]
      }
      // 这里写你要申请的地址
      const result = await this.$ajax.post(`/admin/incentive/queryRewardDetail`,queryObj)
      if (result.data.data) {
        const cardList = result.data.data
        cardList.forEach(e => {this.cardResult.push({value: e.id+' '+e.word, picUrl: e.wordPic, id: e.id})
        });
      }
    },
    handleSelect(item) {this.obj[this.name] = item.id+''   // 选中后给对应项赋值
      this.isShow = false   // 选中某一项后暗藏下拉列表框
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  position: absolute;
  .selectLIst {
    position: relative;
    z-index: 10;
    background-color: #FFFFFF;
    box-shadow: 0 4px 3px #C5C5C5;
    max-height: 200px;
    overflow: auto;
    .item {
      height: 30px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .item:hover {background-color: #EFEFEF;}
  }
  ul {list-style: none   // 暗藏无序列表后面的小圆点}
}
</style>

间接在须要的页面引入并应用:

// item: {word: ''}
// 如果你要将 input 框与 item 的 word 属性绑定,则
<RemoteSearch :obj="item" name='word'/>
退出移动版