在IE上,我可以用jQuery(非常不标准,但工作)做到这一点

if ($.browser.msie)
    $(document).keydown(function(e) { if (e.keyCode == 8) window.event.keyCode = 0;});

但是是否有可能在Firefox上运行,或者在跨浏览器上获得额外的好处呢?

郑重声明:

$(document).keydown(function(e) { if (e.keyCode == 8) e.stopPropagation(); });

什么也不做。

$(document).keydown(function(e) { if (e.keyCode == 8) e.preventDefault(); });

解决了问题,但使退格键在页面上无法使用,这比原来的行为更糟糕。

编辑: 我这样做的原因是我不是在创建一个简单的网页,而是一个大型的应用程序。仅仅因为你在错误的地方按了退格键而失去了10分钟的工作,这是非常令人恼火的。通过防止退格键返回,防止错误和讨厌用户的比例应该远远超过1000/1。

编辑2:我不是想阻止历史航行,只是想阻止事故。

EDIT3: @brentonstrines评论(因为这个问题太受欢迎了,所以移到这里):这是一个长期的“修复”,但你可以支持Chromium bug来改变webkit中的这种行为


当前回答

我很难找到一个非jquery的答案。谢谢斯塔斯让我走上赛道。

Chrome:如果你不需要跨浏览器支持,你可以使用黑名单,而不是白名单。这个纯JS版本可以在Chrome中运行,但不能在IE中运行。不确定FF。

在Chrome(版本。36, 2014年年中),按键不是在输入或可满足的元素似乎是针对<BODY>。这使得使用黑名单成为可能,我更喜欢使用白名单。IE使用最后一次点击目标-所以它可能是一个div或其他任何东西。这使得这个在IE中毫无用处。

window.onkeydown = function(event) {
    if (event.keyCode == 8) {
    //alert(event.target.tagName); //if you want to see how chrome handles keypresses not on an editable element
        if (event.target.tagName == 'BODY') {
            //alert("Prevented Navigation");
            event.preventDefault();
        }
    }
}  

跨浏览器:对于纯javascript,我发现Stas的答案是最好的。增加一个条件检查contentteditable使它为我工作*:

document.onkeydown = function(e) {stopDefaultBackspaceBehaviour(e);}
document.onkeypress = function(e) {stopDefaultBackspaceBehaviour(e);}

function stopDefaultBackspaceBehaviour(event) {
    var event = event || window.event;
    if (event.keyCode == 8) {
        var elements = "HTML, BODY, TABLE, TBODY, TR, TD, DIV";
        var d = event.srcElement || event.target;
        var regex = new RegExp(d.tagName.toUpperCase());
        if (d.contentEditable != 'true') { //it's not REALLY true, checking the boolean value (!== true) always passes, so we can use != 'true' rather than !== true/
            if (regex.test(elements)) {
                event.preventDefault ? event.preventDefault() : event.returnValue = false;
            }
        }
    }
}

*注意ie [edit: and Spartan/TechPreview]有一个“特性”,使与表相关的元素不可编辑。如果你点击其中一个,然后按退格键,它会导航回来。如果你没有editable <td>s,这不是一个问题。

其他回答

以下是我对得票最多的答案的改写。我试着检查element.value!==undefined(因为有些元素可能没有HTML属性,但可能在原型链的某个地方有javascript值属性),然而这并不是很好,并且有很多边缘情况。似乎没有一个很好的方法来证明这一点,所以白名单似乎是最好的选择。

这将在事件气泡阶段的末尾注册元素,因此如果您想以任何自定义方式处理Backspace,您可以在其他处理程序中这样做。

这也检查instanceof HTMLTextAreElement,因为理论上可以有一个继承自它的web组件。

这不会检查contentEditable(与其他答案结合)。

https://jsfiddle.net/af2cfjc5/15/

var _INPUTTYPE_WHITELIST = ['text', 'password', 'search', 'email', 'number', 'date'];

function backspaceWouldBeOkay(elem) {
    // returns true if backspace is captured by the element
    var isFrozen = elem.readOnly || elem.disabled;
    if (isFrozen) // a frozen field has no default which would shadow the shitty one
        return false;
    else {
        var tagName = elem.tagName.toLowerCase();
        if (elem instanceof HTMLTextAreaElement) // allow textareas
            return true;
        if (tagName=='input') { // allow only whitelisted input types
            var inputType = elem.type.toLowerCase();
            if (_INPUTTYPE_WHITELIST.includes(inputType))
                return true;
        }   
        return false; // everything else is bad
    }
}

document.body.addEventListener('keydown', ev => {
    if (ev.keyCode==8 && !backspaceWouldBeOkay(ev.target)) {
        //console.log('preventing backspace navigation');
        ev.preventDefault();
    }
}, true); // end of event bubble phase

结合“toolman”&&“Biff MaGriff”给出的解决方案

下面的代码似乎在IE 8/Mozilla/Chrome中正常工作

$(function () {
    var rx = /INPUT|TEXTAREA/i;
    var rxT = /RADIO|CHECKBOX|SUBMIT/i;

    $(document).bind("keydown keypress", function (e) {
        var preventKeyPress;
        if (e.keyCode == 8) {
            var d = e.srcElement || e.target;
            if (rx.test(e.target.tagName)) {
                var preventPressBasedOnType = false;
                if (d.attributes["type"]) {
                    preventPressBasedOnType = rxT.test(d.attributes["type"].value);
                }
                preventKeyPress = d.readOnly || d.disabled || preventPressBasedOnType;
            } else {preventKeyPress = true;}
        } else { preventKeyPress = false; }

        if (preventKeyPress) e.preventDefault();
    });
}); 

这段代码解决了这个问题,至少在IE和Firefox中是这样(我还没有测试过其他浏览器,但如果其他浏览器也存在这个问题,我认为它有合理的工作机会)。

// Prevent the backspace key from navigating back.
$(document).unbind('keydown').bind('keydown', function (event) {
    if (event.keyCode === 8) {
        var doPrevent = true;
        var types = ["text", "password", "file", "search", "email", "number", "date", "color", "datetime", "datetime-local", "month", "range", "search", "tel", "time", "url", "week"];
        var d = $(event.srcElement || event.target);
        var disabled = d.prop("readonly") || d.prop("disabled");
        if (!disabled) {
            if (d[0].isContentEditable) {
                doPrevent = false;
            } else if (d.is("input")) {
                var type = d.attr("type");
                if (type) {
                    type = type.toLowerCase();
                }
                if (types.indexOf(type) > -1) {
                    doPrevent = false;
                }
            } else if (d.is("textarea")) {
                doPrevent = false;
            }
        }
        if (doPrevent) {
            event.preventDefault();
            return false;
        }
    }
});

我创建了一个NPM项目,使用了目前被接受的(erikkallen)的干净版本

https://github.com/slorber/backspace-disabler

它使用了基本相同的原理,但是:

不依赖 支持知足 更具可读性/可维护性的代码库 当我的公司在生产中使用它时是否会得到支持 麻省理工学院的许可


var Backspace = 8;

// See http://stackoverflow.com/questions/12949590/how-to-detach-event-in-ie-6-7-8-9-using-javascript
function addHandler(element, type, handler) {
    if (element.addEventListener) {
        element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + type, handler);
    } else {
        element["on" + type] = handler;
    }
}
function removeHandler(element, type, handler) {
    if (element.removeEventListener) {
        element.removeEventListener(type, handler, false);
    } else if (element.detachEvent) {
        element.detachEvent("on" + type, handler);
    } else {
        element["on" + type] = null;
    }
}




// Test wether or not the given node is an active contenteditable,
// or is inside an active contenteditable
function isInActiveContentEditable(node) {
    while (node) {
        if ( node.getAttribute && node.getAttribute("contenteditable") === "true" ) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}



var ValidInputTypes = ['TEXT','PASSWORD','FILE','EMAIL','SEARCH','DATE'];

function isActiveFormItem(node) {
    var tagName = node.tagName.toUpperCase();
    var isInput = ( tagName === "INPUT" && ValidInputTypes.indexOf(node.type.toUpperCase()) >= 0 );
    var isTextarea = ( tagName === "TEXTAREA" );
    if ( isInput || isTextarea ) {
        var isDisabled = node.readOnly || node.disabled;
        return !isDisabled;
    }
    else if ( isInActiveContentEditable(node) ) {
        return true;
    }
    else {
        return false;
    }
}


// See http://stackoverflow.com/questions/1495219/how-can-i-prevent-the-backspace-key-from-navigating-back
function disabler(event) {
    if (event.keyCode === Backspace) {
        var node = event.srcElement || event.target;
        // We don't want to disable the ability to delete content in form inputs and contenteditables
        if ( isActiveFormItem(node) ) {
            // Do nothing
        }
        // But in any other cases we prevent the default behavior that triggers a browser backward navigation
        else {
            event.preventDefault();
        }
    }
}


/**
 * By default the browser issues a back nav when the focus is not on a form input / textarea
 * But users often press back without focus, and they loose all their form data :(
 *
 * Use this if you want the backspace to never trigger a browser back
 */
exports.disable = function(el) {
    addHandler(el || document,"keydown",disabler);
};

/**
 * Reenable the browser backs
 */
exports.enable = function(el) {
    removeHandler(el || document,"keydown",disabler);
};

一个更简洁的解决方案是

$(document).on('keydown', function (e) {
    var key = e == null ? event.keyCode : e.keyCode;
    if(key == 8 && $(document.activeElement.is(':not(:input)')))   //select, textarea
      e.preventDefault();
});

或者,您只能检查if

$(document.activeElement).is('body')