Svelte中document.execCommand与queryCommandState失效及编辑器问题
问题解决指南
1. 文本格式化仅选中文本生效的问题
document.execCommand 默认基于当前选区操作,若未选中文本,需确保编辑器处于聚焦状态,命令才会作用于后续输入的文本。修改 formatText 函数:
function formatText(command) { const editor = document.querySelector('[contenteditable="true"]'); editor.focus(); // 确保编辑器聚焦 document.execCommand(command, false, null); updateButtonStates(); // 手动触发按钮状态更新 }
这样即使没有选中文本,点击按钮后后续输入的内容会自动应用对应格式。
2. 按钮激活状态不稳定的问题
核心问题是状态未实时响应选区/光标变化,Svelte 不会自动重新计算class:绑定里的函数调用,需通过响应式变量+事件监听同步状态:
步骤1:定义响应式状态(Svelte 环境)
在 script 块中添加响应式变量:
let isItalicActive = false; let isBoldActive = false; let isUnderlineActive = false; // 统一更新按钮状态的函数 function updateButtonStates() { isItalicActive = document.queryCommandState("italic"); isBoldActive = document.queryCommandState("bold"); isUnderlineActive = document.queryCommandState("underline"); }
步骤2:监听事件同步状态
组件挂载时添加监听,确保状态随选区/光标变化实时更新:
import { onMount, onDestroy } from 'svelte'; onMount(() => { // 监听全局选区变化 document.addEventListener("selectionchange", updateButtonStates); // 监听编辑器的输入、点击事件,确保光标移动时状态更新 const editor = document.querySelector('[contenteditable="true"]'); editor.addEventListener("input", updateButtonStates); editor.addEventListener("click", updateButtonStates); }); onDestroy(() => { // 组件销毁时移除监听,避免内存泄漏 document.removeEventListener("selectionchange", updateButtonStates); const editor = document.querySelector('[contenteditable="true"]'); editor.removeEventListener("input", updateButtonStates); editor.removeEventListener("click", updateButtonStates); });
步骤3:修正按钮的 class 绑定
把原来的函数调用替换为响应式变量(之前写的() => isFormatActive('bold')是错误写法,会因函数本身为真值导致按钮始终激活):
<button class:bg-emerald-950={isItalicActive} on:click={() => formatText("italic")} class="p-4"> <i>I</i> </button> <button class:bg-emerald-950={isBoldActive} on:click={() => formatText("bold")} class="p-4"> <b>B</b> </button> <button class:bg-emerald-950={isUnderlineActive} on:click={() => formatText("underline")} class="p-4"> <u>U</u> </button>
3. bind:innerHTML 的安全隐患及替代方案
安全隐患
直接使用bind:innerHTML会渲染用户输入的原始HTML,若输入包含恶意代码(比如<script>alert('XSS')</script>、<img src=x onerror=stealData()>),会直接执行,引发XSS攻击,窃取用户数据或篡改页面。
安全实现方式
- 纯文本场景:用
bind:textContent
如果不需要富文本,直接绑定文本内容,完全避免HTML解析:
<div contenteditable="true" bind:textContent={editorText}></div>
- 富文本场景:先净化HTML
必须渲染富文本时,使用HTML净化库(如DOMPurify)过滤恶意代码后再绑定:
- 安装依赖:
npm install dompurify - 组件中使用:
import DOMPurify from 'dompurify'; let rawHtml = ''; // 响应式净化HTML $: sanitizedHtml = DOMPurify.sanitize(rawHtml);
<div contenteditable="true" bind:innerHTML={sanitizedHtml}></div>
DOMPurify会自动移除所有恶意脚本和不安全的HTML属性,确保渲染内容安全。
内容的提问来源于stack exchange,提问作者Fuji
相关产品推荐
相关产品推荐

