Skip to content

element-plus 版本 #10

@cshenger

Description

@cshenger

改造了一个element-plus的版本

<template>
  <div
    class="el-input-tag input-tag-wrapper"
    :class="[size ? 'el-input-tag--' + size : '']"
    @click="focusTagInput">
    <el-tag
      v-for="(tag, idx) in innerTags"
      v-bind="$attrs"
      :key="tag"
      :size="size"
      :closable="!readOnly"
      :disable-transitions="false"
      @close="remove(idx)">
      {{tag}}
    </el-tag>
    <input
      v-if="!readOnly"
      class="tag-input el-input__inner"
      :placeholder="placeholder"
      @input="inputTag"
      :value="newTag"
      @keydown.delete.stop = "removeLastTag"
      @keydown = "addNew"
      @blur = "addNew"/>
  </div>
</template>

<script setup name="ElInputTag">
const props = defineProps({
  value: {
    type: Array,
    default: () => []
  },
  addTagOnKeys: {
    type: Array,
    default: () => [13, 188, 9]
  },
  readOnly: {
    type: Boolean,
    default: false
  },
  size: String,
  placeholder: String,
});
// emits
const emits = defineEmits(["update:modelValue"]);

let newTag = ref('');
const innerTags = ref([...props.value]);

// Watch changes in the `value` prop and update `innerTags`.
watchEffect(() => {
  innerTags.value = [...props.value];
});

const focusTagInput = () => {
  if (props.readOnly || !document.querySelector('.tag-input')) {
    return
  } else {
    document.querySelector('.tag-input').focus()
  }
}

const inputTag = (ev) => {
  newTag.value = (ev.target).value;
};

const addNew = (e) => {
  if (
    e &&
    (!props.addTagOnKeys.includes(e.keyCode) ||
      e.type === 'blur')
  ) {
    return;
  }

  e?.stopPropagation();
  e?.preventDefault();

  let addSuccess = false;

  if (newTag.value.includes(',')) {
    newTag.value.split(',').forEach((item) => {
      if (addTag(item.trim())) {
        addSuccess = true;
      }
    });
  } else {
    if (addTag(newTag.value.trim())) {
      addSuccess = true;
    }
  }

  if (addSuccess) {
    tagChange();
    newTag.value = '';
  }
};

const addTag = (tag) => {
  tag = tag.trim();
  if (tag && !innerTags.value.includes(tag)) {
    innerTags.value.push(tag);
    return true;
  }
  return false;
};

const remove = (index) => {
  innerTags.value.splice(index, 1);
  tagChange();
};

const removeLastTag = () => {
  if (!newTag.value) {
    innerTags.value.pop();
    tagChange();
  }
};

const tagChange = () => {
  emits('update:modelValue', innerTags.value);
};

onMounted(focusTagInput);
</script>

<style scoped>
  .el-form-item.is-error .el-input-tag {
      border-color: #f56c6c;
  }
  .input-tag-wrapper {
    position: relative;
    font-size: 14px;
    background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
    background-image: none;
    border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
    cursor: text;
    transition: var(--el-transition-box-shadow);
    transform: translateZ(0);
    box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
    box-sizing: border-box;
    color: #606266;
    display: inline-block;
    outline: none;
    padding: 0 10px 0 5px;
    transition: border-color .2s cubic-bezier(.645,.045,.355,1);
    width: 100%;
  }
  .el-tag {
    margin-right: 4px;
  }

  .tag-input {
    background: transparent;
    border: 0;
    font-size: inherit;
    outline: none;
    padding-left: 0;
    width: 100px;
  }
  .el-input-tag {
    min-height: 42px;
  }
  .el-input-tag--mini {
    min-height: 28px;
    line-height: 28px;
    font-size: 12px;
  }

  .el-input-tag--small {
    min-height: 32px;
    line-height: 32px;
  }

  .el-input-tag--medium {
    min-height: 36px;
    line-height: 36px;
  }
</style>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions