Skip to content

contenteditable 可编辑

contenteditable 全局属性使元素变为可编辑区域,用户可以直接在页面上修改文本内容。它是富文本编辑器的基础,支持文本格式化、图片插入等操作。

前置知识

阅读本节前,建议先了解:draggable 拖拽

基础概念

contenteditable 的值

说明用途
true可编辑富文本编辑区域
false不可编辑显式标记只读内容
plaintext-only仅纯文本只允许纯文本输入

基本用法

html
<!-- 可编辑区域 -->
<div contenteditable="true" style="border:1px solid #ccc;padding:1rem;min-height:100px;">
  <p>点击这里开始编辑...</p>
</div>

<!-- 纯文本编辑 -->
<div contenteditable="plaintext-only" style="border:1px solid #ccc;padding:1rem;">
  只能输入纯文本
</div>

<!-- 混合使用:段落内局部可编辑 -->
<div>
  <p>这段文字不可编辑。</p>
  <p contenteditable="true">这段文字可以编辑。</p>
  <p>这段文字不可编辑。</p>
</div>

语法与使用

execCommand API

contenteditable 配合 document.execCommand() 实现富文本编辑:

javascript
// 执行格式化命令
document.execCommand("bold");       // 加粗
document.execCommand("italic");     // 斜体
document.execCommand("underline");  // 下划线
document.execCommand("strikethrough"); // 删除线
document.execCommand("foreColor", false, "red"); // 文字颜色
document.execCommand("fontSize", false, "5");   // 字号
document.execCommand("insertUnorderedList");   // 无序列表
document.execCommand("insertHTML", false, "<b>插入的内容</b>");

// 检查当前状态
document.queryCommandState("bold");      // 是否加粗
document.queryCommandValue("foreColor"); // 当前颜色

spellcheck 配合使用

html
<!-- 启用拼写检查 -->
<div contenteditable="true" spellcheck="true">
  <p>编辑内容会检查拼写。</p>
</div>

<!-- 禁用拼写检查(适合代码编辑) -->
<div contenteditable="true" spellcheck="false">
  <code>var x = 42;</code>
</div>

详细说明

beforeinput 和 input 事件

html
<div contenteditable="true" id="editor"></div>

<script>
const editor = document.getElementById("editor");

// beforeinput 事件:输入前触发(可以拦截)
editor.addEventListener("beforeinput", (e) => {
  console.log("输入类型:", e.inputType);
  console.log("输入数据:", e.data);

  // 阻止某些输入
  if (e.inputType === "insertParagraph" && e.data === "HTML") {
    e.preventDefault();
  }
});

// input 事件:输入完成后触发
editor.addEventListener("input", (e) => {
  console.log("内容已更改");
  const text = editor.innerText; // 获取纯文本
  const html = editor.innerHTML; // 获取 HTML
});
</script>

contenteditable 的注意事项

注意事项说明
XSS 风险富文本编辑器允许用户输入 HTML,可能导致 XSS 攻击
粘贴处理从其他应用粘贴的内容可能携带不期望的格式
execCommand 废弃虽然仍可用,但建议迁移到 Input Events API
移动端兼容移动设备的虚拟键盘与 contenteditable 交互复杂

实战示例

简易富文本编辑器

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>contenteditable 编辑器示例</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: -apple-system, sans-serif; padding: 2rem; }

    .toolbar {
      display: flex; gap: 0.25rem; padding: 0.5rem;
      background: #f1f5f9; border-radius: 8px 8px 0 0;
      border: 1px solid #e2e8f0; border-bottom: none;
      flex-wrap: wrap;
    }
    .toolbar button {
      padding: 0.4rem 0.75rem; border: 1px solid #d1d5db;
      border-radius: 4px; background: #fff; cursor: pointer;
      font-size: 0.85rem;
    }
    .toolbar button:hover { background: #e2e8f0; }

    .editor {
      border: 1px solid #e2e8f0; border-radius: 0 0 8px 8px;
      padding: 1rem; min-height: 200px; outline: none;
      line-height: 1.6;
    }
    .editor:focus {
      border-color: #3b82f6;
      box-shadow: 0 0 0 3px rgba(59,130,246,0.1);
    }

    .info {
      margin-top: 1rem; padding: 1rem; background: #f8fafc;
      border-radius: 6px; font-size: 0.9rem;
    }
  </style>
</head>
<body>
  <h1>简易富文本编辑器</h1>

  <div class="toolbar">
    <button onclick="exec('bold')" title="加粗"><b>B</b></button>
    <button onclick="exec('italic')" title="斜体"><i>I</i></button>
    <button onclick="exec('underline')" title="下划线"><u>U</u></button>
    <button onclick="exec('strikethrough')" title="删除线"><s>S</s></button>
    <button onclick="exec('insertUnorderedList')" title="无序列表">&#8226;</button>
    <button onclick="exec('foreColor', false, 'red')" title="红色">A(红)</button>
    <button onclick="exec('foreColor', false, 'blue')" title="蓝色">A(蓝)</button>
    <button onclick="exec('fontSize', false, '5')" title="大字号">大</button>
  </div>

  <div class="editor" contenteditable="true">
    <p>在这里编辑内容...</p>
    <p>支持<b>加粗</b>、<i>斜体</i>、<u>下划线</u>等格式。</p>
  </div>

  <div class="info">
    <p>当前内容:<span id="char-count">0</span> 字符</p>
  </div>

  <script>
    function exec(command, value) {
      document.execCommand(command, false, value || null);
    }

    const editor = document.querySelector('.editor');
    const charCount = document.getElementById('char-count');

    editor.addEventListener('input', () => {
      charCount.textContent = editor.innerText.length;
    });
  </script>
</body>
</html>

注意事项

  1. 安全性:必须对用户输入进行消毒处理,防止 XSS
  2. 跨浏览器差异:不同浏览器的粘贴行为和格式化不一致
  3. 移动端兼容:移动设备的虚拟键盘与 contenteditable 交互复杂
  4. 性能:大量内容时 contenteditable 可能导致卡顿

最佳实践

  1. 使用 plaintext-only:如果不需要富文本,使用纯文本模式
  2. 配合 spellcheck:根据内容类型启用或禁用拼写检查
  3. 监听 input 事件:使用 Input Events API 实时获取内容变化
  4. 消毒输出:显示内容时过滤危险的 HTML 标签
  5. 考虑成熟编辑器:生产环境建议使用 Quill、TinyMCE 等成熟方案

下一节

继续学习:spellcheck 拼写检查

参考链接