vue 中 基于el-input 封装 多文本框自定义输入框

该代码段展示了如何在Vue.js中扩展ElementUI的输入框组件,添加自定义的标签功能。通过数据更新、虚拟DOM的更新以及DOM操作,实现了在输入框内显示和管理可关闭的标签。同时,提供了表单校验和禁用状态的支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// 关键就是在数据更新 虚拟dom更新 生成真实dom后在操作 其样式,最终配合定位技术,修改element-input中 原有的样式,添加自己定义的tag标签

<!--
 * @Author: 张沐阳 zhangshuyang@semi-tech.com
 * @Date: 2023-04-24 17:13:17
 * @LastEditors: 张沐阳 zhangshuyang@semi-tech.com
 * @LastEditTime: 2023-04-26 12:03:35
 * @FilePath: \fullyauto-front\src\components\customeInputMutlpleVal\index.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE,
-->
<template>
  <div>
    <!-- 模拟利用element ui实现自定义input的表单的校验 -->
    <el-input v-model="form[modelKey]" readonly placeholder="" ref="cust_input">
    </el-input>
    <div id="tagsBox" ref="tagsBoxRef" style="display: none;">
      <div
        class="cust_input_placeholder"
        v-if="$attrs.placeholder && form[modelKey].length == 0"
      >
        {{ $attrs.placeholder }}
      </div>
      <template v-if="!$slots || Object.keys($slots).length == 0">
        <el-tag
          v-for="(item, index) in form[modelKey]"
          :key="item.id + index + Date.now()"
          :closable="closabledComputed(item)"
          :style="defaultTagStyle"
          @close="onCloseTag(item, index)"
          v-bind="$attrs"
          v-on="$listeners"
          >{{ item[defaultProps.label] }}</el-tag
        >
      </template>
      <slot></slot>
      <slot name="content"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "mutipleValInput",
  inheritAttrs: false,
  props: {
    // tag样式
    tagStyle: {
      type: Object,
      default: () => {
        return {
          display: "inline-block",
          marginRight: "5px",
          marginBottom: "5px"
        };
      }
    },
    // tag取值key
    defaultProps: {
      type: Object,
      default: () => {
        return {
          label: "name"
        };
      }
    },
    // 内部所有tag 统一配置
    canAllclosable: {
      type: Boolean,
      default: true
    },
    // 表单校验的form
    form: {
      type: Object,
      default: () => {}
    },
    // 绑定v-model的key
    modelKey: {
      type: String
    }
  },
  methods: {
    onCloseTag(row, index) {
      this.form[this.modelKey].splice(index, 1);
    },
    setElInputTagBox() {
      this.$nextTick(() => {
        console.log(
          this.$refs.cust_input,
          this.$refs.cust_input.$el,
          this.$refs.cust_input.$refs.input,
          "updated"
        );
        const elInputBox = this.$refs.cust_input.$el;
        const relaInput = this.$refs.cust_input.$refs.input;
        const tagBox = this.$refs.tagsBoxRef;
        elInputBox.style.position = "relative";
        tagBox.style.display = "block";
        this.$attrs.disabled ? tagBox.classList.add("cust_input_disabled") : ""; //添加禁用类名
      });
    }
  },
  data() {
    return {
      defaultTagStyle: {
        display: "inline-block",
        marginRight: "5px",
        marginBottom: "5px"
      }
    };
  },
  computed: {
    closabledComputed() {
      return item => {
        if (this.$attrs.disabled) {
          return !this.$attrs.disabled;
        }
        if (this.canAllclosable) {
          return this.canAllclosable;
        }
        return item.closable;
      };
    }
  },
  created() {
    this.defaultTagStyle = Object.assign(this.defaultTagStyle, this.tagStyle);
  },
  mounted() {
    this.setElInputTagBox()
  },
  updated() {
    this.setElInputTagBox()
  },
  destroyed() {
    console.log(this.form, this.modelKey, "destroyed");
  }
};
</script>

<style lang="scss" scoped>
#tagsBox {
  position: absolute;
  z-index: 2;
  height: 90%;
  width: 99%;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  background: #fff;
  padding: 0 15px;
  cursor: pointer;
}
.cust_input_placeholder {
  color: #c0c4cc;
}
.cust_input_disabled {
  background-color: #f5f7fa !important;
  border: 1px solid #e4e7ed !important;
  color: #c0c4cc !important;
  cursor: not-allowed !important;
  height: 100% !important;
  width: 100% !important;
  border-radius: 4px;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值