自适应高度输入框
文本未超过一行时,保持一行的高度,超出一行时转换为多行样式,类似飞书输入框
发送🎈
源代码
vue
<template>
<div class="input-auto-height" :class="{ focus: onFocusInput }">
<textarea
ref="textareaRef"
@blur="onFocusInput = false"
@focus="onFocusInput = true"
:style="textareaCalcStyle"
v-model="inputValue"
@input="onInput"
></textarea>
<div class="actions" :class="{ 'on-line': onLineSendLayout }">
<div ref="sendBtnRef" class="action-item">发送🎈</div>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
import { getActualWidthOfChars } from '@blinkjun/utils';
import calcTextareaHeight from '../../js/calcTextareaHeight';
const onFocusInput = ref(false);
const onLineSendLayout = ref(true);
const inputValue = ref('');
const textareaRef = ref();
const sendBtnRef = ref();
const textareaCalcStyle = ref({});
function resizeTextarea() {
const minRows = 1;
const maxRows = 7;
textareaCalcStyle.value = calcTextareaHeight(
textareaRef.value,
minRows,
maxRows
);
}
function checkInputSize(value = inputValue.value) {
const width = getActualWidthOfChars(value, {
size: 13,
family: 'monospace',
});
const inputWidth = textareaRef.value.offsetWidth;
const btnWidth = sendBtnRef.value.offsetWidth;
if (inputWidth - btnWidth - width <= 30) {
onLineSendLayout.value = false;
} else {
onLineSendLayout.value = true;
}
}
function onInput(event) {
checkInputSize(event.target.value);
}
watch(inputValue, () => {
resizeTextarea();
});
onMounted(() => {
resizeTextarea();
});
</script>
<style lang="less" scoped>
.input-auto-height {
margin: 10px;
padding: 10px;
position: relative;
border-radius: 6px;
display: flex;
flex-direction: column;
background-color: white;
border: 1px solid transparent;
overflow: hidden;
box-shadow: 0px 3px 4px 0px rgba(33, 42, 57, 0.04);
border: 1px solid rgba(0, 0, 0, 0.05);
&.focus {
border: 1px solid slateblue;
}
textarea {
resize: none;
}
}
.actions {
display: flex;
margin: 6px 12px 6px auto;
&.on-line {
position: absolute;
right: 12px;
top: 0;
bottom: 0;
margin: auto;
height: 26px;
}
.action-item {
background-color: blueviolet;
color: #fff;
cursor: pointer;
padding: 5px 10px;
height: 26px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
}
}
</style>