头图
本文记录一下el-autocomplete的使用和两个常见的问题

需求分析

假设我们有这样的一个需求:

  • 当用户在输入框中输入内容后,呈现关联建议可选项信息,以供用户选择.比如用户输入了“王”这个字,那么要呈现关于“王”的所有的信息,什么“老王”、“王老吉"都出来了,用户点关联的建议可选项,从而方便用户快速输入。
  • 初始情况下,当用户的input输入框获得焦点的时候,与此同时,input输入框中的内容也是没有的时候,就呈现用户之前搜索过得历史记录。
  • 当用户输入了一些文字但是又backspace一个个删除掉了的时候,即当用户把输入框中的文字删除完以后的时候,也就是input输入框的内容为空的时候,再次呈现历史记录
这个时候使用el-autocomplete组件就可以快速解决我们的问题了

el-autocomplete属性介绍

fetch-suggestions属性

绑定的是函数,函数的触发条件是当input输入的时候,或者用户在进入框键入字以后都会触发的,正常情况下回调函数的参数有两个,分别是queryString、和cb。queryString参数代表的值是用户填写到input输入框中的数据值,而cb指的又是一个函数,这里是高阶函数(柯里化)的用法,这里不赘述。cb函数接收的是一个数组,数组里是啥,input输入框关联出现的下拉框就是啥,一一对应的。不过有固定格式要求。因为在el-autocomplete的底层代码里,是有着v-for循环指令的,至于循环的数组就是cb函数传递过来的数组,所以cb函数中的数组内容,也就是输入建议的下拉框的内容

// html部分
:fetch-suggestions="querySearch"

// js部分
querySearch(queryString, cb) {
    cb([
        {value:"老王"},
        {value:"王老吉"} // 数组中的每一项都是一个对象,对象中必须要有value属性,否则不能显示,有没有别的属性不影响。原因是因为源码中定义的就是value字段
    ])
}
// 如果后端给的数据结构不是这种的结构的话,可以使用数组的filter或者map方法自己组装一下数据结构格式

图示如下:

fetch-suggestions也可以传递多个数据,不过要使用闭包的形式才可以,这个后文会举例子再说的。

fetch-suggestions,是用来做关联的数据搜索,用户输入“王”字,获取关联的“老王”、“王老吉”选项值,当用户选中王老吉的时候,如果是一个搜索功能,就需要搜索王老吉的具体资料了,所以这个时候就需要使用el-autocomplete的select属性了

select属性

select绑定的也是一个函数方法,当我们点击选择input输入框关联下拉框某个选项的时候,会拿到下拉框对应项的值。这个值可以传递给后端,用于向后端发请求查询选中的某一条数据的具体信息。

// html部分
@select="handleSelect"

// js部分
handleSelect(item) { // 参数-选中的某一项
  console.log("拿到数据作为参数去向后端发请求",item);
}

trigger-on-focus属性

这个属性的作用是,控制fetch-suggestions是否在el-input获取焦点的时候触发。只要fetch-suggestions触发,就会向后端发请求,就会出现input输入框关联下拉框(输入建议列表),官方定义的是默认为:trigger-on-focus=true,就是输入框输入框一获取焦点,就出现输入建议列表,trigger-on-focus="true"这种方式可以用在获取历史搜索数据场景,毕竟初始情况下可以让后端提供一下历史数据以供用户选择。

当然如果是设置trigger-on-focus="false"的话,这样就不会在初始情况获取焦点的时候出现输入建议列表,在用户输入文字以后才去拿着用户在输入框输入的东西去发请求,问后端要数据。

具体用那种看具体需求。

我们先看一下效果图,再看一下代码

效果图

代码附上

<template>
  <div id="box">
    <el-autocomplete
      :fetch-suggestions="querySearch"
      v-model="inputValue"
      @select="handleSelect"
      :debounce="0"
      :trigger-on-focus="true"
      clearable
      @clear="blurForBug()"
    ></el-autocomplete>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputValue: "",
    };
  },
  methods: {
    //输入框获取焦点时调用的方法
    querySearch(queryString, cb) { // queryString是用户输入的想要查询的内容,cb是回调函数(可以发请求获取数据)
      console.log("如何触发", queryString, cb);
      if (queryString == "") {
        cb([{ value: "历史记录一" }, { value: "历史记录二" }]); // 当然这里的历史记录是后端返给我们的,应该为接口返回的数据
      } else {
        let apiResult = [
          {
            value: "老王",
          },
          {
            value: "王老吉",
          },
        ];
        // 这里我们模拟从后端的接口异步获取的数据
        setTimeout(() => {
          // cb([])    cb函数如果返回一个空数组的话,那个模糊搜索输入建议的下拉选项因为length为0就会消失了
          cb(apiResult);
        }, 500);
      }
    },
    // 选中输入框推荐的值的时候触发
    handleSelect(item) { // 参数
      console.log("拿到数据", item);
    },
    // 点击clearable清空小图标按钮以后,继续重新在输入框中输入数据,querySearch会触发,但是cb函数不会触发
    // 这样的话就会出现发请求了,也获取数据了,但是input框的输入建议下拉框不呈现在页面上的问题,所以解决方法就是
    // 只要用户点击了
    blurForBug(){
      document.activeElement.blur()
    }
  },
};
</script>

<style lang="less" scoped>
#box {
  width: 100%;
  height: 600px;
  box-sizing: border-box;
  padding: 50px;
}
</style>

常见问题

点击 clearable清除按钮输入建议失效

我们会发现,如果给el-autocomplete组件标签加上clearable属性以后,那么,当我们输入内容以后,再点击clearable清空按钮清空输入框中输入的数据以后,当我们再重新输入文字的时候,请求会触发,后端返给我们的数据也获取到了,但是后端返回给我们的数据却没有渲染到页面上。就仿佛输入没反应了。解决方案比较直接的就是,当用户点击了clearable清空按钮以后,就让当前获取焦点的输入框失去焦点,回到最初状态,一切重新开始

即为:主动触发失去焦点,解决‘fetch-suggestions’输入建议失效的bug,也就是:@clear="blurForBug()"

传递多个参数(使用闭包)

html部分

<el-autocomplete
  v-model="inputValue"
  @select="handleSelect"
  :debounce="0"
  :trigger-on-focus="true"
  clearable
  @clear="blurForBug()"
 :fetch-suggestions="
      (queryString, cb) => {
        multipleFn(queryString, cb, index);
      }
    "
></el-autocomplete>

js部分

multipleFn(queryString, cb, index) {
    console.log(queryString, cb, index)
}

注意上述html部分中的:fetch-suggestions的写法,这里使用闭包的写法,这样的话,就可以传递多个参数了。因为如果某个功能模块有好多个el-autocomplete,这样的话,我们就要使用v-for去循环出来,可能需要把item,index什么的传递给后端,那么这个时候,传递多个参数就是必须滴了,这个时候使用上述闭包的方式就能解决问题啦


水冗水孚
1.1k 声望588 粉丝

每一个不曾起舞的日子,都是对生命的辜负