textarea 文本输入框实现不同颜色字体方案
在做一个短信/邮件模板配置的功能时,例如下图,需要在文本 textarea
组件内输入需要给用户发送的短信内容,但是每个人的姓名是不一样的,需要后端在发送短信时,将字符串里一些固定的变量(约定了变量用#号包裹)替换成真实的用户名。
难点在于 textarea 内的变量需要用不同字体颜色
进行展示,以便做区分,很合理的一个需求。
富文本方案
富文本编辑器当然时终极完美的解决方案啦,富文本功能强大,如果这个短信/邮件配置模板后面有各种复杂功能时,还是建议使用富文本,说不定哪天产品经理说要支持图片素材的短信/邮件呢!
但是富文本编辑器也有几个缺点(我强行想出来的😄)
- 引入富文本需要加载过多资源,内存会占用大,如果只是实现变量不同字体颜色展示,有点杀鸡用牛刀感觉
- 如果功能简单(例如只支持文本输入)的话,使用富文本可能还需要屏蔽掉富文本上的许多功能入口
contenteditable 方案
在一个html元素上设置 contenteditable = 'true'
即可让元素可以变成可编辑状态,我相信这也是很多人能够想到的一种可能实现的方式。但是理想很丰富,显示很骨感,contenteditable还是有很多坑,反正实现起来还是挺复杂的,实际上有些富文本编辑器的技术也是利用了此特性来实现的,有兴趣的读者可以自己尝试去折腾下。
textarea 绝对定位方案
我在业余时间捣鼓了一种方式,在 textarea 输入框下面隐藏一份p标签,p标签内容即文本输入框输入的内容,不同的是下面的p标签内容是html格式的,可以支持颜色显示的。
<div style="position:relative">
<!--隐藏在下面,用于展示颜色-->
<p style="width:400px;padding:8px;white-space:pre-wrap" v-html="inputText2" />
<!--绝对定位在上面-->
<p style="position: absolute;z-index: 1;top:0;left:0" class="textarea-wrap">
<el-input
ref="myTextArea"
:model-value="inputText"
autosize
type="textarea"
autofocus
style="width:400px; "
@input="textChange"
@change="textChange"
/>
</p>
</div>
js逻辑就是文字输入完后,将变量字符串替换成span标签,并设置span的样式,span有个核心样式:
position:relative;z-index:10000;
这样可以使得蓝色字体不会被输入框所遮挡住。
const textChange = (val) => {
inputText.value = val
inputText2.value
= inputText.value
.replaceAll('#姓名#', '<span style=\'color:#409eff;position:relative;z-index:10000;\'>#姓名#</span>')
.replaceAll('#待上传文件总数#', '<span style=\'color:#409eff;position:relative;z-index:10000;\'>#待上传文件总数#</span>')
}
textarea输入框样式如下,这里以element-ui为例,其他框架雷同。
.textarea-wrap .el-textarea__inner{
color:rgba(0,0,0,1);
padding: 8px;
caret-color: black;
background: transparent;
font-size:16px;
}
有几点需要注意,p标签内的字体大小需要和文本框字体大小一致,这样就可以完全重叠,使得用户感知不到。
此方案代码简单,实现起来比较轻量,性能好,在一些简单业务场景下还是可以使用的,但是对于复杂的配置模板需求,我建议还是使用富文本编辑器吧😏
完
转载自:https://juejin.cn/post/7241057752070668344