利用一个隐藏的 <span>(称为 mirror)渲染当前输入内容:
-
该
span使用与<el-input>相同的字体样式; -
每次输入时,根据
span.offsetWidth动态计算内容宽度; -
将该宽度赋给
<el-input>的style.width; -
给输入框增加少许 padding 余量,保证视觉舒适。
<template> <el-form :model="form" label-width="auto" class="auto-form"> <el-form-item label="Activity name">{{ form.name || placeholder }}</el-form> </template> <script lang="ts" setup> import { ref, reactive, onMounted, nextTick } from 'vue'<!-- 自适应宽度的 el-input --> <el-input v-model="form.name" :style="{ width: inputWidth + 'px' }" :placeholder="placeholder" class="auto-el-input" @input="updateWidth" /> </div> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">Create</el-button> <el-button @click="onCancel">Cancel</el-button> </el-form-item>// 表单数据
const form = reactive({
name: ''
})// 占位文字(用于在空值时计算最小宽度)
const placeholder = '请输入活动名称'// 输入框宽度(默认最小 100px)
const inputWidth = ref(100)
const mirror = ref<HTMLElement | null>(null)// 动态更新输入框宽度
const updateWidth = () => {
if (mirror.value) {
// 同步文字
mirror.value.textContent = form.name || placeholder
// 计算宽度 + 内边距
inputWidth.value = mirror.value.offsetWidth + 24
}
}onMounted(async () => {
await nextTick()
updateWidth()
})const onSubmit = () => {
console.log('提交数据:', form)
}const onCancel = () => {
<style scoped> .auto-form { max-width: 500px; margin: 40px auto; }
form.name = ''
updateWidth()
}
</script>.input-auto-wrapper {
display: inline-block;
position: relative;
}.mirror {
position: absolute;
visibility: hidden;
white-space: pre;
font: inherit; /* 与 el-input 保持一致 */
padding: 0 12px;
}.auto-el-input {
transition: width 0.2s ease;
}
</style>限制最大宽度
inputWidth.value = Math.min(mirror.value.offsetWidth + 24, 400)此方案无需修改 Element Plus 源码,通过一个简单的隐藏
span即可实现原生级别的动态自适应宽度输入框效果