1. 为什么要自定义呢?
原生的 input 和 textarea 在某些特定场景下存在功能或兼容性限制,因此使用 div 元素自定义实现,突破原生输入框在样式、功能、兼容性上的限制。
1、解决火狐浏览器换行问题
某些版本的火狐浏览器中,原生 textarea 存在回车不换行而显示为空格的问题。这种行为在开发文本编辑器或多行输入框时造成不便。
2、提供更灵活的样式和内容格式
原生 input 和 textarea 元素样式定制有限,比如:无法直接改变 textarea 的行高或在内容中插入动态元素,如:标签或图标。原生输入框的内容只能是纯文本,难以直接支持复杂的文本格式,如:加粗、斜体或自定义样式。
3、跨平台或多浏览器兼容
不同的浏览器和设备对原生输入框的支持程度有所不同,尤其是一些老旧浏览器或特定版本的浏览器可能会对 input 和 textarea 产生不同的渲染结果。
2. 实现方法
contenteditable = "true" 是一个 HTML 属性,能够将 div 或其他元素变成一个可编辑的区域。用户可以输入文本,而浏览器会处理光标、输入等基本交互行为。通过监听相应的事件,可以让这个可编辑的 div 元素实现更复杂的行为和功能。
2.1 实现带 placeholder 的输入框
div 本身并没有内建的 placeholder 属性,但可以使用 CSS 和 JavaScript 来模拟该功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.custom-input {
border: 1px solid #ccc;
padding: 5px;
border-radius: 4px;
outline: none;
word-wrap: break-word; /* 自动换行 */
white-space: pre-wrap; /* 支持空格换行 */
overflow-y: auto;
position: relative;
}
.custom-input-wrapper {
position: relative;
}
.custom-input:empty::before {
content: attr(data-placeholder); /* 使用 data-placeholder */
color: #aaa;
position: absolute;
top: 5px;
left: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<div class="custom-input-wrapper">
<div class="custom-input" contenteditable="true" data-placeholder="请输入内容..."></div>
</div>
<script>
const inputBox = document.querySelector('.custom-input');
// 监听输入事件,动态处理内容为空时显示 placeholder
inputBox.addEventListener('input', () => {
if (!inputBox.textContent.trim()) {
inputBox.setAttribute('data-placeholder', '请输入内容...');
} else {
inputBox.removeAttribute('data-placeholder');
}
});
</script>
</body>
</html>
效果展示:
2.2 实现内容插入到光标位置
插入内容到光标位置是自定义输入框中非常常见的需求,例如:在文本框中插入表情符号或链接等。通过 JavaScript 中的 Range 和 Selection API,可以精确控制光标位置。
<button>插入内容</button>
<div class="custom-input" contenteditable="true" data-placeholder="请输入内容..."></div>
<script>
function insertTextAtCursor(text) {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
range.deleteContents(); // 删除选中内容
const textNode = document.createTextNode(text);
range.insertNode(textNode); // 插入新内容
range.setStartAfter(textNode); // 设置光标到插入文本后
range.collapse(true); // 合并范围
selection.removeAllRanges();
selection.addRange(range);
}
document.querySelector('button').addEventListener('click', () => {
insertTextAtCursor('插入的内容');
});
</script>
效果展示:
3. 优缺点
3.1 优点
1、兼容性
使用 word-wrap: break-word 和 white-space: pre-wrap,可以确保不同浏览器中实现的换行行为一致。
2、灵活性
可以完全自定义样式和行为,比如控制光标的样式、输入框的大小、边框样式等。此外,使用 JavaScript 可以更加方便地动态插入和编辑内容。
3、支持插入光标位置
通过 Selection 和 Range API,可以精确的将文本插入到当前光标位置。
3.2 缺点
1、事件监听复杂
与原生的 input 和 textarea 不同,设置 contenteditable = "true" 的元素需要手动管理 placeholder 的显示与隐藏,处理焦点事件(focus、blur)和输入事件等,增加开发复杂性。
2、内容格式问题
由于 div 中的内容是可以包含 HTML 的,用户可能会误输入 HTML 标签或其他不合适的内容,要求开发者处理内容时格外小心,避免引发 XSS(跨站脚本攻击)等安全问题,且需要对输入内容进行过滤和清理。
3、性能问题
对于输入内容较长的情况,频繁的 DOM 操作可能会导致性能下降,尤其是当需要处理大量内容时,可能会影响用户体验。
4. 存在问题
4.1 控制输入内容长度
contenteditable 默认不限制输入,需要额外监听 input 事件并判断长度。
inputBox.addEventListener('input', () => {
const maxLength = 200;
if (inputBox.textContent.length > maxLength) {
inputBox.textContent = inputBox.textContent.slice(0, maxLength);
}
});
4.2 处理用户粘贴带有 HTML 内容
用户粘贴内容时,可能会不小心粘贴带有 HTML 标签的内容。我们可以通过监听 paste
事件,过滤粘贴内容,只保留纯文本:
inputBox.addEventListener('paste', (event) => {
event.preventDefault();
const text = event.clipboardData.getData('text/plain');
document.execCommand('insertText', false, text);
});
总结
使用 contenteditable="true" 属性,可以实现一个高度自定义、功能强大的输入框,克服原生 input 和 textarea 的局限性。
标签:textarea,自定义,输入框,内容,inputBox,input,div,placeholder From: https://blog.csdn.net/weixin_52648900/article/details/145032650