惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
IT之家
IT之家
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Security Archives - TechRepublic
Security Archives - TechRepublic
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
P
Palo Alto Networks Blog
Know Your Adversary
Know Your Adversary
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cisco Talos Blog
Cisco Talos Blog
L
Lohrmann on Cybersecurity
AWS News Blog
AWS News Blog
J
Java Code Geeks
博客园_首页
Scott Helme
Scott Helme
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
T
The Exploit Database - CXSecurity.com
Security Latest
Security Latest
V
Visual Studio Blog
Cloudbric
Cloudbric
Jina AI
Jina AI
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
S
SegmentFault 最新的问题
The Last Watchdog
The Last Watchdog
SecWiki News
SecWiki News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
W
WeLiveSecurity
K
Kaspersky official blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Hacker News: Ask HN
Hacker News: Ask HN
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
量子位
Google Online Security Blog
Google Online Security Blog
博客园 - Franky
Simon Willison's Weblog
Simon Willison's Weblog
博客园 - 三生石上(FineUI控件)
Recent Commits to openclaw:main
Recent Commits to openclaw:main

博客园 - Mc525

antv3 x6 基本语法-流程图(二) element ui el-form 表单错误 滚动可视区域 vue2 element ui el-table大数据处理无分页解决方案-分片加载 vue2 地图热力图 -下钻省市县 三级及地图资源文件 vue2 组件封装 el-select vue2 组件封装 el-date-picker 日期 vue2 scss sass 基础安装包、安装依赖报错 !!! vue2 封装组件使用 v-mode【el-radio,el-input】 Mac Jenkins 环境部署 vue2 按钮权限(七) vue2 换肤(六) vue2 项目实例 国际化(五) vue2 项目实例 动态路由菜单(四) vue2 项目实例 Mock数据模拟(三) vue2 项目实例 Layout布局(二) vue2 项目实例 项目初始化(一) vue2 项目架构--api.js(七) vue2 项目架构--vue.config.js(七) vue2 项目架构--main.js(六)
vue2 组件封装 el-input
Mc525 · 2025-11-14 · via 博客园 - Mc525

 组件支持:

  • 基础的 v-model 双向绑定
  • 防抖 / 节流功能(通过属性配置)
  • 支持 el-input 原生属性透传
  • 支持插槽(如前置 / 后置图标

customInput

     index.vue.  // 组件页面

     index.js.    全局注册使用

index.vue

<template>
  <el-input
    v-bind="$attrs"
    v-on="$listeners"
    :value="value"
    @input="handleInput"
    @change="handleChange"
    :placeholder="placeholder"
    :type="type"
    clearable
    :disabled="disabled"
    show-word-limit
  >
    <!-- 透传所有具名插槽和默认插槽 -->
    <template v-for="(slot, name) in $slots" :slot="name">
      <slot :name="name"></slot>
    </template>
  </el-input>
</template>
<script>
import _ from 'lodash'; // 引入 lodash
// import { debounce, throttle } from '@/utils/index'; // 导入自定义函数
export default {
  name: "CustomInput",
  props: {
    value: {
      type: [String, Number],
      default: "",
    },
    // 防抖配置
    debounce: {
      type: [Number, Boolean],
      default: false,
    },

    // 节流配置
    throttle: {
      type: [Number, Boolean],
      default: false,
    },
    // 去除首尾空格
    autoTrim: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: "请输入",
    },
    clearable: {
      type: Boolean,
      default: true,
    },
    type: {
      type: String,
      default: "text",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否显示字数统计
    showWordLimit: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      // 存储防抖/节流函数的引用
      debouncedInput: null,
      throttledInput: null,
    };
  },
  created() {
    // 初始化防抖函数
    if (this.debounce) {
      const delay = typeof this.debounce === "number" ? this.debounce : 500;
      this.debouncedInput = _.debounce(this.emitInput, delay);
    }

    // 初始化节流函数
    if (this.throttle) {
      const interval = typeof this.throttle === "number" ? this.throttle : 500;
      this.throttledInput = _.throttle(this.emitInput, interval);
    }
  },
  beforeDestroy() {
    // 组件销毁前取消防抖/节流
    if (this.debouncedInput) this.debouncedInput.cancel();
    if (this.throttledInput) this.throttledInput.cancel();
  },
  computed: {
    // maxlength() {
    //   return this.$attrs.maxlength;
    // }
  },
  mounted() {},
  methods: {
    // 输入事件处理
    handleInput(val) {
      if (this.debounce) {
        this.debouncedInput(val); // 防抖处理
      } else if (this.throttle) {
        this.throttledInput(val); // 节流处理
      } else {
        this.emitInput(val); // 无防抖节流
      }
    },
    // 失去焦点时触发(确保最终值被更新)
    handleChange(val) {
      this.emitInput(val, true);
    },

    // 触发 input 事件更新值
    emitInput(val, isChange = false) {
      // 如果是 change 事件触发,直接更新
      if (isChange) {
        this.$emit('input', val);
        return;
      }

      // 否则根据配置更新
       const finalValue = this.autoTrim ? val.trim() : val;
      this.$emit('input', finalValue);
    },
  },
};
</script>

index.js.

import CustomInput from './index.vue';

CustomInput.install = function(Vue) {
  Vue.component(CustomInput.name, CustomInput);
};

export default CustomInput;

//main.js  注册全局。vue.use(custominput)

页面使用

     <el-form-item label="输入框" prop="name">
        <my-input
          v-model="ruleForm.name"
          placeholder="请输入哈哈"
        > 
           <i slot="suffix" class="el-input__icon el-icon-date"></i>
      </my-input>
      </el-form-item>

image

关键点解析:

  • $slots: 这是一个对象,包含了父组件传递给当前组件的所有插槽。
  • v-for="(slot, name) in $slots": 遍历 $slots 对象,name 是插槽名称(如 prefixsuffix),slot 是插槽内容。
  • :slot="name": 将遍历出的插槽内容,以其原始名称透传到内部的 el-input 上。
  1. v-bind="$attrs": 这是实现 Props 透传最关键的一步。它会将父组件传递给 MyInput 但没有在 props 中声明的所有属性,全部绑定到内部的 el-input 上。例如 placeholderdisabledmaxlengthtype 等 el-input 支持的原生属性,你都无需在 MyInput 的 props 中重新定义,直接就能用。

  2. v-on="$listeners": 这是事件转发的关键。它会将父组件在 MyInput 上监听的所有事件(如 blurfocuschange),全部转发到内部的 el-input 上。这样,父组件使用 @blur 就和直接使用 el-input 的体验一致。

  3. slot 插槽与原有保持一致