富文本编辑器里怎么实现格式刷功能?

司马卫红 阅读 19

我正在用 contenteditable 做一个简单的富文本编辑器,现在想加个格式刷功能,就是点一下复制当前选中文本的样式,再点另一段文字就应用过去。但不知道怎么准确获取和还原样式,试过 window.getSelection() 拿到 range,但样式信息好像不全。

有没有人做过类似的功能?比如 Quill 或 TinyMCE 里那种格式刷,核心逻辑是怎样的?我是不是得遍历所有父级节点的 computedStyle?

我来解答 赞 11 收藏
二维码
手机扫码查看
1 条解答
露露 ☘︎
最简单的办法是别去遍历 computedStyle,那玩意儿太重而且算出来的值往往不是你想要的(比如颜色会转成 rgb)。利用浏览器原生的 queryCommandValue 把当前选区的核心状态存起来,再用 execCommand 刷过去就行。虽然 execCommand 被标记为废弃,但做这种轻量级功能它依然是最好用的 API,不用自己造轮子。

核心逻辑就是两步:点一下存状态,再点一下遍历执行 execCommand。

let isPainting = false;
let currentStyles = [];

// 支持的样式命令,按需添加
const styleCommands = ['bold', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'fontName', 'fontSize'];

// 获取当前选区样式
function pickFormat() {
currentStyles = styleCommands.map(cmd => ({
cmd: cmd,
value: document.queryCommandValue(cmd)
}));
isPainting = true;
console.log('样式已吸取', currentStyles); // 调试用
}

// 应用样式到新选区
function applyFormat() {
if (!isPainting) return;

currentStyles.forEach(style => {
if (style.value && style.value !== 'false') { // 排除空值
document.execCommand(style.cmd, false, style.value);
}
});

// 单次模式:刷完一次自动关闭,如果想要像 Word 那样连续刷,把这行去掉
isPainting = false;
currentStyles = [];
}

// 绑定事件示例
document.getElementById('format-brush-btn').addEventListener('click', () => {
if (!isPainting) {
pickFormat();
} else {
isPainting = false; // 取消格式刷状态
}
});

// 监听选区变化,如果在刷模式下,选区变了就自动应用(或者你可以设计成再次点击按钮才应用)
document.addEventListener('selectionchange', () => {
// 注意:selectionchange 触发很频繁,实际开发建议加个防抖或者设计成点击应用
// 这里为了演示简单,不直接在这里调用 applyFormat,而是建议用户选中后再次点击工具栏按钮触发 applyFormat
});
点赞 6
2026-03-03 20:04