封装一个用vue+element-ui实现的远程搜索组件(vue-cli项目中)

1.在components下新建一个RemoteSearch.vue文件(或者新建一个文件夹,命名RemoteSearch,下面加入一个index.vue文件)(命名都是自己随意的)
2.RemoteSearch.vue文件内容如下

<template>
  <div class="autocomplete">
    <el-autocomplete
      v-model="searchValue"
      :maxlength="maxlen"
      :fetch-suggestions="querySearchAsync"
      :placeholder="placeholder"
      @select="handleSelect"
      :show-word-limit="false"
      @focus="focusFn"
      @blur="blurFn"
      @change="changeFn"
      placement="top"
    >
     // 这里是给远程搜索组件加上字数限制和icon
      <div slot="suffix">
        <span v-if="ifshowWordLimit">{{ searchValue.length }}/{{ maxlen }}</span>
        <i class="el-icon-arrow-up" v-if="searchUp"> </i>
        <i class="el-icon-arrow-down" v-else> </i>
      </div>
    </el-autocomplete>
  </div>
</template>
<script>
export default {
  name: 'remote-search',
  data() {
    return {
      timeout: null,
      searchValue: this.value,
      searchUp: false,
    };
  },
  props: {
    //这个value值是可以获取到父组件的v-model值的,可以实现父子组件的双向绑定
    value: {
      type: String,
      default: '',
    },
   /* 存放数据的数组,element-ui有个bug,
     就是这个数组必须是[{value:'www.baidu.com'}]的形式,
     所以在传数组的时候必须做处理 */
    options: {
      type: Array,
      default: () => {},
    },
   // 最大值
    maxlen: {
      type: Number,
      default: 1000,
    },
   // 默认文案
    placeholder: {
      type: String,
      default: '请输入链接',
    },
   /*开始是想在父组件来传这个值赋值给子组件来实现父子组件双向绑定,
    但是用value父组件就不需要传这个了*/
    defaultVal: {
      type: String,
      default: '',
    },
   // 是否显示字数限制
    ifshowWordLimit: {
      type: Boolean,
      default: false,
    },
  },
  watch: {
   // 必须用watch来监听一下这个值,因为要响应父组件的校验
    searchValue() {
      this.validateTextarea();
    },
   /*在watch中把value赋值给searchValue来实现父子组件双向绑定,
     如果用defaultValue直接赋值给data就行 */
    value(val) {
      this.searchValue = val;
    },
  },
  methods: {
    focusFn() {
      this.searchUp = true;
    },
    querySearchAsync(queryString, cb) {
      // 判断是否查询后台的条件
      // if (this.options.filter(this.createStateFilter(queryString)) && this.options.filter(this.createStateFilter(queryString)).length !== 0) {
      let options = this.options;
      let results = queryString ? options.filter(this.createStateFilter(queryString)) : options;
      if (results && results.length > 0) {
        this.searchUp = true;
      } else {
        this.searchUp = false;
      }
      cb(results);
    },
    // 查询输入字符是否存在
    createStateFilter(queryString) {
      return searchValue => {
        // 这里和elementui组件不一样
        // value可以换成从后端传回的data数组中的键,
        // queryString.toLowerCase()输入的字符在所有返回信息中存在,!==-1代表匹配到了搜索的字符,
        // 官方的==0是搜索的字符在第一个字才会匹配,!=-1指的是只要是内容中只要有搜索的字符就会返回匹配**
        return searchValue.value.toLowerCase().indexOf(queryString.toLowerCase()) !== -1;
      };
    },
    blurFn() {
      this.searchUp = false;
      // console.log('blur', this.searchValue);
    },
    handleSelect(item) {
      // 返回的意见点击选择触发事件
      this.searchValue = item.value;
      // console.log('blursdfsd', this.searchValue);
      this.$emit('change', this.searchValue);
    },
    // 传值给父组件,并响应父组件input事件
    validateTextarea() {
      try {
        // console.log('input', this.searchValue);
        this.$emit('input', this.searchValue);  // 传值给父组件并响应input事件
      } catch (e) {
        // this.$emit('error', true);
      }
    },
    changeFn(item) {
      // console.log('change', item);
      this.searchValue = item;
      this.$emit('change', this.searchValue);
    },
  },
};
</script>
<style lang="scss" scoped>
.autocomplete {
  width: 100%;
  .el-autocomplete {
    width: 100%;
  }
  /deep/ .el-input__suffix {
    line-height: 40px;
  }
}
</style>

3.使用

<template>
<RemoteSearch v-model="skipUrl" ref="remoteSearch" :options="options"/>
</template>
<script>
import RemoteSearch from '@/asset/components/RemoteSearch.vue'; // 引入子组件
export default {
 components: {
    RemoteSearch,
  },
 data() {
return {
      options: [{value:'餐厅'},{value:'水果店'}],  // 传给远程搜索组件的数据
      rules: {
        skipUrl: [
          { required: true, message: '请输入链接', trigger: ['change', 'blur'] }, // 必须要用change事件
        ]
      },
    };
  }
}
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容