背景:
实现一个自适应高度的输入框, 空格与换行每次最多只能输入一个;
尝试 与 思路
首先想到的就是 textarea, 但是需要设置高度或者行数 rows, 这样超出设定就会出现 滚动条, 而且空格与换行还是可以无限输入
enmmm... 然后想到貌似 div 也可以;
<div contenteditable="true"></div> 这样的设置也可以输入, 效果相比 textarea 也不差多少
但是 div 不支持 placeholder, 还需要自己模拟, 还有同样的问题就是 空格与换行可以连续无限输入; 在各个浏览器与移动端设备跑一跑, 发现显示效果并不理想 (〃´皿`)q 只能放弃~
既然如此那还是换回 textarea 吧, 毕竟对于输入而言, 它还是很专业的
接下来需要解决的问题就是
1. 处理输入的内容, 使 空格 换行 不可无限输入
2. 处理 自适应的问题
下面使用 vue 的方式为例:
HTML 部分
<!-- VUE -->
<div id='mainBox'>
<div class="Box">
<div class="InputBox">
<textarea class="font" @input="textareaChange($event)" v-model='textareaText' placeholder="请输入评论" ></textarea>
<p class="font" v-html='pCont'></p>
</div>
</div>
</div>
CSS 样式部分
.Box {
width: 50%;
height: auto;
display: block;
padding: 5px 10px;
margin: 20px auto;
border: 1px solid rgba(0, 0, 0, 0.3);
}
.Box .InputBox {
width: 100%;
min-height: 20px;
display: block;
position: relative;
}
.Box .InputBox > .font {
font-size: 14px;
line-height: 20px;
font-family: Arial, Helvetica, sans-serif;
}
.Box .InputBox > textarea {
width: 100%;
height: 100%;
display: block;
position: absolute;
top: 0%;
left: 0%;
z-index: 10;
resize: none;
outline: none;
background: none;
color: rgba(0, 0, 0, 0.7);
}
.Box .InputBox > p {
width: 100%;
display: block;
min-height: 20px;
opacity: 0;
}
JS 部分
new Vue ({
el: '#mainBox',
data () {
return {
textareaText: '', // 用于赋值给 textarea
pCont: '' // 用于赋值给 P 标签
}
},
methods:{
/** 实时监听输入框动态 */
textareaChange(e){
const self = this
let strCont = e.target.value.replace(/\n\s(\s)*/gi, '\n') // 将多个回车换行合并为 1个
strCont = strCont.replace(/^\s*/gi, '') // 清除首行的 空格与换行
let strHtml = strCont.replace(/</gi, '<') // 将所有的 < 转义为 < 防止html标签被转义
strHtml = strCont.replace(/\n(\n)*/gi, '<br>') // 回车换行替换为 <br>
strHtml = strHtml.replace(/\s+/gi, ' ') // 一个或过个空格 替换为
strCont = strHtml.replace(/ /gi, ' ') // 逆向处理
strCont = strCont.replace(/<br>/gi, '\n') // 逆向处理
strCont = strCont.replace(/</gi, '<')
self.textareaText = strCont
/** 如果 p 标签最后的字符为 <br> 并不会单独另起一行, 会导致与 textarea 的高度相差一行,
* 所以在最后添加一个字符, 这样就能保证 P 标签的高度与 textarea 的高度一致
*/
self.pCont = strHtml+'.'
},
}
})
解释
用 P 标签撑起父控件, 然后 texterea 属性设置为 absolute, 这样就能保证 texterea 与 父组件的大小一致
又因为 P 标签的内容 与 texterea 输入的内容 格式字体大小样式等一致, 所以 就实现了输入框自适应的效果
测试了部分浏览器与移动端设备, 支持效果都还不错, 至少能保证样式一致, 特殊字符什么的基本也没出现错位等显现