【Vue】二次封装elementUI自定义样式的input搜索框

【Vue】二次封装elementUI自定义样式的input搜索框

接手的项目中多处使用了一个按照设计稿样式的搜索框,为了提高复用率,对其进行封装。
以此文章做工作记录

1. 整体效果

按照项目的需要,要实现的功能比较简单:

  • 自定义的清空图标
  • 可控输入框右边是否有按钮
  • 回车/输入事件都可触发搜索
    【Vue】二次封装elementUI自定义样式的input搜索框_第1张图片
    【Vue】二次封装elementUI自定义样式的input搜索框_第2张图片

代码关键点:

  • 使得外部v-model的绑定正常工作
  • 组件内部对外部数据的清空
  • 其他输入框事件的绑定

2. 如何使得外部v-model正常工作

众所周知v-model是输入框双向绑定的语法糖,本质上是

:value="value" @input="value = $event.target.value"

组件使用v-model,也就是相当于给组件绑定了一个value值,和一个input事件。
因此在组件内接收即可:

export default {
	name:"SearchInput",
    props:{
      value: [String, Number]
    }
}

然后对组件内的input标签绑定好value值,这里的@input直接$emit触发外部的input事件,并且传入参数$event
v-bind="$attrs"用于值的绑定穿透,能直接把没有在props声明的其他绑定值,直接传递到内部的el-input框,只要有这个,直接在组件外面绑定的placeholder值,class值都会直接同步到这里。

v-on="$listeners"同理,指的是事件的绑定穿透,另外还有$scopedSlots插槽穿透,这里并不需要所以不拓展说明。

    <el-input
      :value="value"
      @input="$emit('input', $event)"
      v-bind="$attrs"
    >
    el-input>

这样外部的v-model就可以正常工作了。

3. 补充自定义的样式和事件绑定

按照项目原本的需求,补充自定义的样式,还有el-input的插槽。
至于清空输入的按钮,按照设计稿,没有使用原生的clearable属性,而是添加作为el-input的suffix插槽。

  • prefix前置:搜索图标
  • suffix后置:清空输入的图标
  • append附加:搜素按钮
<i slot="prefix"><img :src="CommonImg.search" alt="">i>
<i slot="suffix" v-if="empty" class="el-icon-close" @click="handleClear">i>
<el-button slot="append" v-if="hasBtn"  type="primary" @click="$emit('enter',value)">搜索el-button>

搜索按钮根据外部传入的参数决定:

    props:{
      value: [String, Number],
      hasBtn:Boolean
    }

清空输入图标的出现按照当前是否有输入决定
由于vue的单向数据流,不提倡在子组件内部直接修改父组件的参数,因此清空输入不是给value清空,而是是触发外部的函数来进行清除。

    watch:{
      value(newValue){
        if(newValue !== ''){
          this.empty = true;
        }else{
          this.empty = false;
        }
      },
    },
    methodes:{
    	//清除输入
      handleClear() {
        this.$emit('input', '');
        this.$emit('change', '');
        this.$emit('clear');
      },
    }

4. SearchInput源码

这里根据需要添加了一些操作和回调…
此外,组件内还可以更改外界v-model绑定的变量
虽然默认绑定值是value,事件是input
但可以在vc配置里面的model属性,修改为checkedchange 等用于其他作用。

<template>
  <div>
    <el-input
      :value="value"
      @input="$emit('input', $event)"
      v-bind="$attrs"
      @mouseenter="hovering = true"
      @mouseleave="hovering = false"
      @focus="handleFocus"
      @blur="handleBlur"
      @keyup.native.enter="handleEnter"
    >
      <i slot="prefix"><img :src="CommonImg.search" alt="">i>
      <i slot="suffix" v-if="empty" class="el-icon-close" @click="handleClear">i>
      <el-button slot="append" v-if="hasBtn"  type="primary" @click="$emit('enter',value)">搜索el-button>
    el-input>
  div>
template>

<script>
import {CommonImg} from '@/assets'
  export default {
    name:"SearchInput",
    props:{
      value: [String, Number],
      hasBtn:Boolean
    },
    data(){
      return {
        CommonImg,
        hovering: false,
        focused: false,
        empty:false,
      }
    },
    watch:{
      value(newValue){
        if(newValue !== ''){
          this.empty = true;
        }else{
          this.empty = false;
        }
      },
    },
    methods:{
      handleFocus(event) {
          this.focused = true;
          this.$emit('focus', event);
      },
      handleBlur(event) {
          this.focused = false;
          this.$emit('blur', event);
      },
      handleEnter(){
        // 这里可以包一个防抖 handleEnter:debounce(function(){ ... })
        if(this.value === '') return;
        this.$emit('enter',this.value)
      },
      handleClear() {
        this.$emit('input', '');
        this.$emit('change', '');
        this.$emit('clear');
      },
    },
  }
script>
<style lang="less" scoped>
	//...样式自定义
style>

5. 使用例:

点击搜索按钮,使用回车进行查询的类型:

<SearchInput v-model="warningInfoSearchInput" 
	placeholder="请输入任务名称检索" hasBtn
	@enter="warningInfoSearch"/>

输入内容就查询的类型:

<SearchInput placeholder="请输入关键字检索"
   v-model="searchInfo" @input="changeSearchInfo" />

你可能感兴趣的:(vue.js,elementui,前端)