令人满意的变革事件

Jou*_*key 334 javascript jquery html5 contenteditable

我想在用户编辑divwith contenteditable属性的内容时运行一个函数.什么相当于一个onchange事件?

我正在使用jQuery,所以任何使用jQuery的解决方案都是首选.谢谢!

Tim*_*own 275

我建议将侦听器附加到可编辑元素触发的关键事件,尽管您需要注意keydownkeypress在更改内容本身之前触发事件.这不会涵盖更改内容的所有可能方法:用户还可以使用编辑或上下文浏览器菜单中的剪切,复制和粘贴,因此您可能也想要处理cut copypaste事件.此外,用户可以删除文本或其他内容,因此那里有更多事件(mouseup例如).您可能希望将元素的内容轮询为回退.

更新2014年10月29日

HTML5 input事件是在长期的答案.在撰写本文时,它支持contenteditable当前Mozilla(来自Firefox 14)和WebKit/Blink浏览器中的元素,但不支持IE.

演示:

document.getElementById("editor").addEventListener("input", function() {
    console.log("input event fired");
}, false);
Run Code Online (Sandbox Code Playgroud)
<div contenteditable="true" id="editor">Please type something in here</div>
Run Code Online (Sandbox Code Playgroud)

演示:http://jsfiddle.net/ch6yn/2691/

  • 我还应该补充说,可以通过使用浏览器的编辑菜单或上下文菜单来切换,复制或粘贴内容来更改可编辑元素,因此您需要在浏览器中处理`cut`,`copy`和`paste`事件支持他们(IE 5 +,Firefox 3.0 +,Safari 3 +,Chrome) (11认同)
  • 你可以使用keyup,你不会有时间问题. (4认同)
  • @Blowsie:是的,但是你可能最终会在事件发生之前发生自动重复按键发生的很多变化.还有其他方法可以更改此答案未考虑的可编辑文本,例如通过编辑和上下文菜单进行拖放和编辑.从长远来看,这应该全部由HTML5`input`事件涵盖. (2认同)

bal*_*ton 179

这是一个更有效的版本,on用于所有contenteditables.它基于这里的最佳答案.

$('body').on('focus', '[contenteditable]', function() {
    const $this = $(this);
    $this.data('before', $this.html());
}).on('blur keyup paste input', '[contenteditable]', function() {
    const $this = $(this);
    if ($this.data('before') !== $this.html()) {
        $this.data('before', $this.html());
        $this.trigger('change');
    }
});
Run Code Online (Sandbox Code Playgroud)

该项目在这里:https://github.com/balupton/html5edit

  • 在满足模糊之前,此代码不会捕获一些更改.例如:拖放,从上下文菜单中剪切,以及从浏览器窗口粘贴.我已经设置了一个使用此代码的示例页面,您可以与[here](http://jrullmann.github.com/contenteditable-onchange-approaches/)进行交互. (7认同)

jru*_*ann 51

考虑使用MutationObserver.这些观察者旨在对DOM中的变化做出反应,并作为Mutation Events的高效替代品.

优点:

  • 当发生任何变化时触发,这很难通过听取其他答案建议的关键事件来实现.例如,所有这些都运行良好:拖放,斜体,通过上下文菜单复制/剪切/粘贴.
  • 设计时考虑到性能.
  • 简单,直接的代码.理解和调试侦听一个事件的代码比听取10个事件的代码要容易得多.
  • Google有一个出色的变异汇总库,可以很容易地使用MutationObservers.

缺点:

  • 需要最新版本的Firefox(14.0+),Chrome(18+)或IE(11+).
  • 要理解的新API
  • 目前还没有关于最佳实践或案例研究的大量信息

学到更多:

  • 我写了一个小片段来比较使用MutationObserers来处理各种事件.我使用了balupton的代码,因为他的回答是最赞成的.
  • Mozilla在API上有一个很好的页面
  • 看一下MutationSummary

  • @citykid:那是因为该片段只是在观察角色数据的变化.也可以观察DOM结构变化.例如,参见http://jsfiddle.net/4n2Gz/1/. (4认同)
  • 它与 HTML5 的“input”事件不太一样(在所有支持突变观察者的 WebKit 和 Mozilla 浏览器中都支持“contenteditable”),因为 DOM 突变可以通过脚本和用户输入发生,但它是一个可行的方法。这些浏览器的解决方案。我认为它对性能的损害也比“输入”事件更大,但我没有确凿的证据证明这一点。 (2认同)
  • +1,但您是否意识到变异事件不会报告线路馈送的影响?在代码段中按Enter键. (2认同)

Dev*_*pia 21

非jQuery快速和肮脏的答案:

function setChangeListener (div, listener) {

    div.addEventListener("blur", listener);
    div.addEventListener("keyup", listener);
    div.addEventListener("paste", listener);
    div.addEventListener("copy", listener);
    div.addEventListener("cut", listener);
    div.addEventListener("delete", listener);
    div.addEventListener("mouseup", listener);

}

var div = document.querySelector("someDiv");

setChangeListener(div, function(event){
    console.log(event);
});
Run Code Online (Sandbox Code Playgroud)

  • 这个删除事件是什么? (3认同)

Den*_*ter 20

我修改了lawwantsin的答案,这对我有用.我使用keyup事件而不是keypress工作得很好.

$('#editor').on('focus', function() {
  before = $(this).html();
}).on('blur keyup paste', function() { 
  if (before != $(this).html()) { $(this).trigger('change'); }
});

$('#editor').on('change', function() {alert('changed')});
Run Code Online (Sandbox Code Playgroud)


bit*_*ess 15

两种选择:

1)对于现代(常绿)浏览器: “输入”事件将充当替代“更改”事件。

https://developer.mozilla.org/en-US/docs/Web/Events/input

document.querySelector('div').addEventListener('input', (e) => {
    // Do something with the "change"-like event
});
Run Code Online (Sandbox Code Playgroud)

或者

<div oninput="someFunc(event)"></div>
Run Code Online (Sandbox Code Playgroud)

或(使用 jQuery)

$('div').on('click', function(e) {
    // Do something with the "change"-like event
});
Run Code Online (Sandbox Code Playgroud)

2)考虑到 IE11 和现代(常绿)浏览器: 这会监视 div 中的元素更改及其内容。

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

var div = document.querySelector('div');
var divMO = new window.MutationObserver(function(e) {
    // Do something on change
});
divMO.observe(div, { childList: true, subtree: true, characterData: true });
Run Code Online (Sandbox Code Playgroud)

  • 只需使用“input”事件即可!如果需要支持 IE11,请使用突变观察器。爱它。简明扼要。 (2认同)

小智 5

const p = document.querySelector('p')
const result = document.querySelector('div')
const observer = new MutationObserver((mutationRecords) => {
  result.textContent = mutationRecords[0].target.data
  // result.textContent = p.textContent
})
observer.observe(p, {
  characterData: true,
  subtree: true,
})
Run Code Online (Sandbox Code Playgroud)
<p contenteditable>abc</p>
<div />
Run Code Online (Sandbox Code Playgroud)

  • 这看起来很有趣。有人可以提供一些解释吗? (2认同)