封装组件--input组件

在观看element的源码以后,开始封装自己的input组件,相对于源码封装还有很多不完善,后期后继续努力。

 一、实现功能

        1. input中内容的删除图标,2. 密码的加密和解密,3. input的获取焦点和失去焦点事件。

        4. placeHolder和禁用等。5. 自动获取焦点。

        其中的字体图标需要自己去图标库自己下载哦。

二、子组件接受的属性

props: {
    value: [String, Number],
    placeholder: {
      type: String,
      default: "请输入"
    },
    disabled: {
      type: Boolean,
      default: false
    },
    type: {
      type: String,
      default: "text"
    },
    prefixIcon: String,
    suffixIcon: String,
    showPasswrod: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: false
    },
    autoFoucs: {
      type: Boolean,
      default: false
    }
  },

三、功能实现

        和源码相差还很大,自己完善完善一起学习吧。

        代码如下:

<template>
  <div
    :class="[
      type === 'textarea' ? 'zc-textarea' : 'zc-input',
      {
        'zc-input-group--prepend': $slots.prepend,
        'zc-input-group--append': $slots.append,
        'zc-input-group': $slots.prepend || $slots.append,
        'zc-input--prefix': $slots.prefix || prefixIcon,
        'zc-input--suffix': $slots.suffix || suffixIcon
      }
    ]"
  >
    <template v-if="type !== 'textarea'">
      <!-- 前置元素 -->
      <div v-if="$slots.prepend" class="zc-input-group__prepend">
        <slot name="prepend"></slot>
      </div>
      <input
        :type="showPasswrod ? (passwordVisible ? 'text' : 'password') : type"
        :disabled="disabled"
        @focus="handleFocus"
        @blur="handelBlur"
        @change="handleChange"
        @input="handleInput"
        ref="input"
        :placeholder="placeholder"
        class="el-input_inner"
        :class="getClass"
      />
      <!-- 前置内容 -->
      <span class="zc-input__prefix" v-if="$slots.prefix || prefixIcon">
        <slot name="prefix"></slot>
        <i class="zc-input__icon" v-if="prefixIcon" :class="prefixIcon"></i>
      </span>
      <!-- 后置内容 -->
      <span class="zc-input__suffix">
        <template v-if="!showPasswrod">
          <slot name="suffix"></slot>
          <i class="zc-input__icon" v-if="suffixIcon" :class="suffixIcon"></i>
        </template>
        <!-- 密码展示 -->
        <i
          class="zc-input__icon zc-input_show"
          :class="passwordVisible ? 'zc-icon-shared' : 'zc-icon-collect'"
          v-if="showPasswrod && nativeInputValue() && !disabled"
          @click="handlePasswordVisible"
        ></i>
        <!-- 清空按钮 -->
        <i
          class="zc-input__icon zc-input_clear"
          :class="clearable && nativeInputValue() ? 'zc-icon-shared' : ''"
          @mousedown.prevent
          @click="handleClear"
        ></i>
      </span>
      <!-- 后置元素 -->
      <div class="zc-input-group__append" v-if="$slots.append">
        <slot name="append"></slot>
      </div>
    </template>
  </div>
</template>



js代码 

<script>
export default {
  name: "ZcInput",
  data() {
    return {
      passwordVisible: false,
      focus: false
    }
  },
  props: {
    value: [String, Number],
    placeholder: {
      type: String,
      default: "请输入"
    },
    disabled: {
      type: Boolean,
      default: false
    },
    type: {
      type: String,
      default: "text"
    },
    prefixIcon: String,
    suffixIcon: String,
    showPasswrod: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: false
    },
    autoFoucs: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    getClass() {
      return [
        { "is-disabled": this.disabled, "zc-input_inner": this.$slots.prepend }
      ]
    }
  },
  mounted() {
    // this.setNativeInputValue()
    // eslint-disable-next-line eqeqeq
    if (this.autoFoucs) {
      this.$refs.input.focus()
    }
  },
  methods: {
    nativeInputValue() {
      return this.value === null || this.value === undefined
        ? ""
        : String(this.value)
    },
    getInput() {
      return this.$refs.input || this.$refs.textarea
    },

    handleFocus(event) {
      this.focus = true
      this.$emit("focus", event)
    },
    handelBlur(event) {
      this.focus = false
      this.$emit("blur", event)
    },
    handlePasswordVisible() {
      this.passwordVisible = !this.passwordVisible
    },
    setNativeInputValue() {
      const input = this.getInput()
      if (!input) return
      if (input.value === this.nativeInputValue()) return
      input.value = this.nativeInputValue()
    },
    handleClear() {
      this.$emit("input", "")
      this.$emit("change", "")
      this.$emit("clear")
      this.$nextTick(() => {
        this.setNativeInputValue()
      })
    },
    handleInput(event) {
      // should not emit input during composition
      // see: https://github.com/ElemeFE/element/issues/10516
      // if (this.isComposing) return
      // hack for https://github.com/ElemeFE/element/issues/8548
      // should remove the following line when we don't support IE
      // if (event.target.value === this.nativeInputValue) return
      this.$emit("input", event.target.value)
      // ensure native input value is controlled
      // see: https://github.com/ElemeFE/element/issues/12850
      // this.$nextTick(this.setNativeInputValue())
    },
    handleChange(event) {
      this.$emit("change", event.target.value)
    }
  }
}
</script>

css样式 

<style lang="scss">
.zc-input {
  position: relative;
  width: 100%;
  font-size: 14px;
  display: inline-block;
}
.el-input_inner {
  width: 100%;
  height: 40px;
  border: 1px solid #dcdfe6;
  padding: 0 15px;
  box-sizing: border-box;
  border-radius: 4px;
  color: #606266;
  font-size: inherit;

  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  &:focus {
    outline: none;
    border-color: #409eff;
  }
}
.zc-input_inner {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.is-disabled {
  cursor: not-allowed;
  background: #f5f7fa;
  border-color: #e4e7ed;
  color: #c0c4cc;
}
.zc-input-group {
  display: inline-table;
  border-spacing: 0;
}
.zc-input-group__append,
.zc-input-group__prepend {
  display: table-cell;
  background: #f5f7fa;
  color: #909399;
  width: 1px;
  padding: 0 20px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  border-radius: 4px;
}
.zc-input-group__prepend {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: 0;
}
.zc-input__prefix {
  position: absolute;
  top: 0;
  left: 5px;
  color: #c0c4cc;
}
.zc-input__icon,
.zc-input__prefix {
  height: 100%;
  text-align: center;
  transition: all 0.3s;
}
.zc-input__icon {
  width: 25px;
  line-height: 40px;
}
.zc-input--prefix .el-input_inner {
  padding-left: 30px;
}
.zc-input--suffix .el-input_inner {
  padding-right: 30px;
}

.zc-input__suffix {
  position: absolute;
  right: 5px;
  top: 0;
  color: #c0c4cc;
}
.zc-input_clear,
.zc-input_show {
  cursor: pointer;
}
.zc-input-group__append {
  border-left: 0;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.zc-input-group--append .el-input_inner {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
</style>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成序猿@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值