当textarea里的内容超过一行后,会出现滚动条并隐藏前一行的内容,特别是在移动端使用到textarea多行文本输入的话,这样显示其实是很不友好的。所以要做一个可根据内容改变高度的textarea的组件。由于项目是使用的vue写的所以就用vue举例了。
1.首先创建一个setTextarea.js用于存放设置高度的方法
setTextarea.js
let hiddenTextarea;
const HIDDEN_STYLE = `
height:0 !important;
visibility:hidden !important;
overflow:hidden !important;
position:absolute !important;
z-index:-1000 !important;
top:0 !important;
right:0 !important
`;
const CONTEXT_STYLE = [
"letter-spacing",
"line-height",
"padding-top",
"padding-bottom",
"font-family",
"font-weight",
"font-size",
"text-rendering",
"text-transform",
"width",
"text-indent",
"padding-left",
"padding-right",
"border-width",
"box-sizing",
];
function calculateNodeStyling(targetElement) {
const style = window.getComputedStyle(targetElement);
const boxSizing = style.getPropertyValue("box-sizing");
const paddingSize =
parseFloat(style.getPropertyValue("padding-bottom")) +
parseFloat(style.getPropertyValue("padding-top"));
const borderSize =
parseFloat(style.getPropertyValue("border-bottom-width")) +
parseFloat(style.getPropertyValue("border-top-width"));
const contextStyle = CONTEXT_STYLE.map(
(name) => `${name}:${style.getPropertyValue(name)}`
).join(";");
return { contextStyle, paddingSize, borderSize, boxSizing };
}
export default function calcTextareaHeight(
targetElement,
minRows = 1,
maxRows = null
) {
if (!hiddenTextarea) {
hiddenTextarea = document.createElement("textarea");
document.body.appendChild(hiddenTextarea);
}
let {
paddingSize,
borderSize,
boxSizing,
contextStyle,
} = calculateNodeStyling(targetElement);
hiddenTextarea.setAttribute("style", `${contextStyle};${HIDDEN_STYLE}`);
hiddenTextarea.value = targetElement.value || targetElement.placeholder || "";
let height = hiddenTextarea.scrollHeight;
const result = {};
if (boxSizing === "border-box") {
height = height + borderSize;
} else if (boxSizing === "content-box") {
height = height - paddingSize;
}
hiddenTextarea.value = "";
let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
if (minRows !== null) {
let minHeight = singleRowHeight * minRows;
if (boxSizing === "border-box") {
minHeight = minHeight + paddingSize + borderSize;
}
height = Math.max(minHeight, height);
result.minHeight = `${minHeight}px`;
}
if (maxRows !== null) {
let maxHeight = singleRowHeight * maxRows;
if (boxSizing === "border-box") {
maxHeight = maxHeight + paddingSize + borderSize;
}
height = Math.min(maxHeight, height);
}
result.height = `${height}px`;
hiddenTextarea.parentNode &&
hiddenTextarea.parentNode.removeChild(hiddenTextarea);
hiddenTextarea = null;
return result;
}
2.使用
引入setTextarea.js
<template>
<div >
<textarea ref="textarea" v-model="machine.acceptdtl" :style="{'height': height}" maxlength="1000" @input="inputRule" @blur="onBlur" class="multi-line-input"></textarea>
</div>
</template>
<script>
import calcTextareaHeight from '@/plugins/setTextarea'
export default {
name: 'TodayWork',
data() {
return {
height: '',
machine: {
acceptdtl: ''
}
}
},
mounted() {
this.getHeight();
},
methods: {
getHeight() {
this.height = calcTextareaHeight(this.$refs.textarea, 1, null).height;
},
inputRule() {
},
onBlur() { }
},
watch: {
'machine.acceptdtl': {
handler: function () {
this.getHeight();
},
},
}
}
</script>
<style scoped lang="scss">
.multi-line-input {
width: 99%;
min-height: auto;
height: auto;
resize: none;
}
</style>