创建内联编辑器需要付出努力。首先使用 input
或 textarea
字段切换要编辑的元素。为了获得无缝的用户体验,您可能还需要使用一些 CSS 以使交换元素的样式与原始元素相匹配。用户完成编辑后,将所有内容复制到原始内容后,您将不得不再次切换元素。
contentEditable
属性使此任务变得更加容易。您所要做的就是将此属性设置为 true
,标准 HTML5 元素将变得可编辑。在本教程中,我们将基于此功能创建一个内联富文本编辑器。
该属性可以采用三个有效值。它们是 true
、false
和 继承
。值 true
表示该元素是可编辑的。空字符串也将计算为 true。 false
表示该元素不可编辑。值 inherit
是默认值。 inherit
指示如果元素的直接父元素可编辑,则该元素将可编辑。这意味着,如果您使元素可编辑,则其所有子元素(不仅仅是直接元素)也将变得可编辑,除非您显式将其 contentEditable
属性设置为 false
。< /p>
您可以使用 JavaScript 动态更改这些值。如果新值不是三个有效值中的任何一个,则会抛出 SyntaxError
异常。
要创建内联编辑器,您需要能够在用户决定编辑某些内容时更改 contentEditable
属性的值。
在切换 contentEditable
属性时,有必要知道该属性当前拥有什么值。为此,您可以使用 isContentEditable
属性。如果 isContentEditable
对于某个元素返回 true
,则该元素当前可编辑,否则不可编辑。我们很快就会使用这个属性来确定文档中各种元素的状态。
首先,我们需要创建一个名为contenteditable-editor的目录。在其中创建一个名为 index.html 的新文件。您可以将其用作 HTML 文件的骨架。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Text Editor</title> </head> <body></body> </html>
构建编辑器的第一步是创建一个用于切换编辑和一些可编辑元素的按钮。在 元素内,输入:
<button id="editBtn" type="button">Edit Document</button> <div id="editor"> <h1 id="title">A Nice Heading.</h1> <p>Last Edited By - <span id="author">Monty Shokeen</span></p> <p id="content">Some content that needs correction.</p> </div>
我们打算保持可编辑的每个元素都需要有自己唯一的 Id
。当我们必须保存更改或稍后检索它们以替换每个元素内的文本时,这将很有帮助。
以下 JavaScript 代码处理所有编辑和保存。
const editBtn = document.getElementById('editBtn'); const editables = document.querySelectorAll('#title, #author, #content') editBtn.addEventListener('click', function(e) { if (!editables[0].isContentEditable) { editables[0].contentEditable = 'true'; editables[1].contentEditable = 'true'; editables[2].contentEditable = 'true'; editBtn.innerHTML = 'Save Changes'; editBtn.style.backgroundColor = '#6F9'; } else { // Disable Editing editables[0].contentEditable = 'false'; editables[1].contentEditable = 'false'; editables[2].contentEditable = 'false'; // Change Button Text and Color editBtn.innerHTML = 'Enable Editing'; editBtn.style.backgroundColor = '#F96'; // Save the data in localStorage for (var i = 0; i < editables.length; i++) { localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML); } } });
您可以将此代码放在 标签中,该标签位于
标签的底部。我们使用
querySelectorAll()
将所有可编辑元素存储在变量中。此方法返回一个 NodeList
,其中包含文档中与指定选择器匹配的所有元素。这样,就可以更轻松地使用一个变量来跟踪可编辑元素。例如,我们文档的标题可以通过使用 editables[0]
来访问,这就是我们接下来要做的。
接下来,我们向按钮的单击事件添加一个事件侦听器。每次用户单击“编辑文档”按钮时,我们都会检查标题是否可编辑。如果它不可编辑,我们将每个可编辑元素上的 contentEditable
属性设置为 true
。此外,文本 '编辑文档'
更改为 '保存更改'
。用户进行一些编辑后,可以单击 '保存更改'
按钮,所做的更改可以永久保存。
如果标题可编辑,我们将每个可编辑元素的 contentEditable
属性设置为 false。此时,我们还可以将文档内容保存在服务器上,以便稍后检索或将更改同步到其他地方存在的副本。在本教程中,我将把所有内容保存在 localStorage
中。将值保存在 localStorage
中时,我使用每个元素的 Id
以确保不会覆盖任何内容。
如果您对上一个演示中的任何元素进行更改并重新加载页面,您会发现所做的更改消失了。这是因为没有适当的代码来检索保存的数据。将内容保存到 localStorage
后,当用户再次访问该网页时,我们需要检索它。
if (typeof(Storage) !== "undefined") { if (localStorage.getItem('title') !== null) { editables[0].innerHTML = localStorage.getItem('title'); } if (localStorage.getItem('author') !== null) { editables[1].innerHTML = localStorage.getItem('author'); } if (localStorage.getItem('content') !== null) { editables[2].innerHTML = localStorage.getItem('content'); } }
上面的代码检查标题、作者或内容是否已存在于 localStorage
中。如果是,我们将相应元素的 innerHTML
设置为检索到的值。
为了让编辑器更加人性化,我们应该添加自动保存功能。第一种方法每五秒自动保存您的工作。
setInterval(function() { for (var i = 0; i < editables.length; i++) { localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML); } }, 5000);
您还可以保存每个 keydown
事件的更改。
document.addEventListener('keydown', function(e) { for (var i = 0; i < editables.length; i++) { localStorage.setItem(editables[i].getAttribute('id'), editables[i].innerHTML); } });
在本教程中,我坚持使用后一种方法。您可以根据项目中合适的任何事件自由触发自动保存。
现在,我们需要让人们轻松插入新标题和其他格式元素。为此,我们添加一个工具栏。首先,我们需要添加一些 HTML。将此代码段添加到 标记的顶部。
<div id="toolbar"> <button id="addh1">H1</button> <button id="addh2">H2</button> </div>
现在,让我们让它真正发挥作用。我们需要添加一个 click
事件,将标题插入到内容块中。
document.querySelector("#addh1").addEventListener("click", function (e) { const text = prompt( "What text do you want the heading to have?", "Heading" ); editables[2].innerHTML = editables[2].innerHTML + `<h1>${text}</h1>`; });
这会将 click
事件附加到 H1 按钮,该事件提示您使用 prompt()
函数输入文本,并将该文本放入内容块内的标题中。如果需要,您还可以像编辑普通文本一样编辑标题。要为 H2s 添加此功能,您只需更改元素选择器和插入的 HTML 即可。
document.querySelector("#addh2").addEventListener("click", function (e) { const text = prompt( "What text do you want the heading to have?", "Heading" ); editables[2].innerHTML = editables[2].innerHTML + `<h2>${text}</h2>`; });
您可以轻松地将其扩展到其他元素,例如粗体文本和下划线,只需创建一个新行以及插入新选择器和不同 HTML 标记的上述代码版本即可。
目前,编辑器没有 CSS。您可以随心所欲地设计它,但我们也为您预制了一种样式。如果您想要与我在代码笔中使用的样式相同的样式,可以使用此 CSS。
body { font-family: Arial; font-size: 1.3em; line-height: 1.6em; } .headline { font-size: 2em; text-align: center; } #wrapper { width: 600px; background: #fff; padding: 1em; margin: 1em auto; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); border-radius: 3px; } button { border: none; padding: 0.8em; background: #f96; border-radius: 3px; color: white; font-weight: bold; margin: 0 0 1em; } button:hover, button:focus { cursor: pointer; outline: none; } #editor { padding: 1em; background: #e6e6e6; border-radius: 3px; }
要测试您的工作,您可以使用 serve
之类的东西。要使用服务,您只需运行 npm i -gserve
,然后在包含您的工作的目录中运行 serve
。 serve
将自动启动包含您的 HTML 文件的网络服务器,您可以通过单击打印的链接导航到该文件。
contentEditable
当您必须编辑网页上的一些元素时非常有用。当网页上所有或几乎所有元素的内容必须更改时,可以使用 designMode
属性。该属性适用于整个文档。要将其打开 on
和 off
,请使用 document.designMode = 'on';
和 document.designMode = 'off';
分别。
在您是设计师而其他人是内容创建者的情况下,这将证明是有价值的。您向他们提供设计和一些虚拟文本。稍后,他们可以用真实的内容替换它。要查看 designMode
的实际运行情况,请在浏览器的开发人员工具中打开控制台选项卡。在控制台中输入 document.designMode = 'on';
并按 Enter。此页面上的所有内容现在都应该可以编辑。
contentEditable
属性在快速编辑文章或使用户只需单击一下即可编辑评论等情况下非常方便。该功能首先由 IE 5.5 实现。后来被WHATWG标准化。浏览器支持也很好。除 Opera Mini 之外的所有主流浏览器都支持此属性。
JavaScript 已成为网络工作的标准语言之一。它并非没有学习曲线,而且还有大量的框架和库可以让您忙碌起来。如果您正在寻找其他资源来学习或在工作中使用,请查看我们在 Envato 市场中提供的资源。
本教程介绍了 contentEditable
属性的基础知识,以及如何使用它来创建基本的内联文本编辑器,以及如何添加按钮以实现丰富的格式设置。
这篇文章已根据 Jacob Jackson 的贡献进行了更新。 Jacob 是一名 Web 开发人员、技术作家、自由职业者和开源贡献者。