为什么 Firefox 对“select”标签上的“click”事件的react与 Webkit 和 IE 不同?

IT技术 javascript html internet-explorer firefox webkit
2021-03-05 05:55:17

我意识到 Firefox 处理标签上的点击事件<select>与 Webkit/IE 不同,我无法弄清楚为什么或如何解决这种差异。

具体而言,Webkit的/ IE将每个点击事件上<select> 作为组合两个点击“选择”,下拉的一个的点击<option>,在下面曲线图所示:

第一次点击:

首先点击

第二次点击:

第二次点击

在 Webkit/IE 中,只有在两次点击都完成后才会触发click事件。

但是在Firefox中,<select>标签的第一次点击被视为一个点击事件,第二次点击选择<option>被视为另一个点击事件。因此,2个 点击事件已经在Firefox解雇比较一个WebKit中/ IE进行同样的操作。

现在在代码示例中演示它,假设我们有:(JSfiddle 链接

<select id="sel">
    <option>one</option>
    <option>two</option>
    <option>three</option>​
</select>
<script>
function select() {
    $("#sel").one("click", function(event) {
        console.log('mouse down!');
        $("#sel").one('click', function() {
            console.log('mouse down again!');
            $("#sel").off();
            select();
        });
    });
}
$(document).ready(function() {
    select();
});
</script>

在 Webkit/IE 中,执行上图中显示的一组操作(第一次)将给出输出:

mouse down!

在 Firefox 中,它会给出:

mouse down!
mouse down again!

为什么会这样,我该如何解决?

编辑:我尝试使用没有 jQuery 的纯 JavaScript,结果保持不变。

编辑 2:多一点上下文,我最初回答了这个问题:onclick on option 标签不适用于 IE 和 chrome,并为我的回答赢得了赏金。但是,正如操作员后来指出的那样,我的解决方案在 Firefox 上不起作用。我决定深入挖掘以解决这个问题,因此提出了这个问题,我奖励了我从该解决方案中获得的 50 赏金。本质上,问题在于创建一个选择菜单,该菜单将在做出选择时触发一个事件,即使它是相同的。事实证明,这比预期的要困难,如果可能的话,由于不同的浏览器实现。

编辑 3:我完全知道onchange,但这里的问题不是关于onchange你是否仔细阅读。我需要让每个选择触发一个事件,即使它们是相同的选择(这不会触发onchange.

3个回答

为什么不使用onchange事件?

$("#sel").change(function(){
    $('body').append("<br/> Option changed");
});

这是小提琴

但即使选择相同,它也不会触发。解决方法是按照另一个答案中的建议使用像 Chosen 这样的插件。

编辑:从哲学上讲,select元素并不适用于此类功能。changeevent 足以满足大多数与select标签相关的用例您想要的功能,即了解用户是否对元素进行了选择(即使它没有改变),不适合select标签的功能模型从逻辑上讲,select如果他/她不想更改选择,则没有人会想要单击元素。

为了满足您的要求,除了您的 select 标签之外,您还可以使用Go button并调用onclick您通常onchangeselect元素事件执行的相同函数否则给出一个悬停卡/悬停菜单 而不是select.

由于问题与点击事件有关,因此我没有答案。但问题的解决方案是使用正确的事件。这可能是onchange。正如@juzerali 所写。学术笔记:点击事件是否在 ecmascript 中准确指定?- 唔。这可能是您问题的答案:“未指定”。
2021-04-21 05:55:17
onchange 是一个好的开始,但如果您使用键盘进行选择,它会过于频繁地触发。也许您的插件将此归功于此。你知道吗?
2021-04-23 05:55:17
似乎这一定是 OSx 和 jsFiddle 上的 FF 的问题。mozilla 网站上示例确实有效,但复制到 jsFiddle 中的相同 HTML 无效。
2021-04-23 05:55:17
@LosManos 恕我直言,我的问题已经明确说明这onchange根本不是一个选项,因为即使选择相同,即没有改变,也需要触发所需的效果感谢您的指导,我可能应该更早地查看 ECMAScript 规范的定义。我的猜测是你是对的,因为这种行为可能在不同的浏览器中被模糊地定义和解释。
2021-04-24 05:55:17
感谢您的投入。但是我的问题根本不是关于onchange你自己的问题,你的问题不会在选择相同时发射事件。我的问题只是关于为什么在不同的浏览器中会出现这种差异onchange以及如何在使用它时让它消失。
2021-05-07 05:55:17

经过多次实验和搜索,我开始确信,如果可能的话,在不同浏览器中这种特殊的不同行为很难解决。

然而,我意识到,我可以从另一方面解决问题,通过使用jQuery UI 选择菜单选择来创建选择菜单而不是使用<select>标签。这种方式click将触发事件<ul><li>标记,这在我测试的所有浏览器中都是一致的。

我认为答案是——由于不同的 JavaScript 引擎和实现——在这些不同浏览器上的行为不会与click事件相同,“解决方案”是更改 HTML(就像你在这里说的)或更改JavaScript 事件(如 juzerali 所说)。
2021-04-30 05:55:17
谢谢!我遇到了同样的问题,最终我使用了Chosen,它比普通的select.根据可用性问题最好使用本机控件,但此时设计对我来说更重要。
2021-05-03 05:55:17
我认为区别在于 Chrome 中,您单击的是一个虚假选项列表,而在 Firefox 中,您实际上是单击了选项元素。你试过什么if(!$(event.target).is('option')) ...;吗?
2021-05-05 05:55:17
@kmfk 谢谢,是的,我确实event.stopPropagation在实验中尝试过,但也无济于事..
2021-05-08 05:55:17
@Kay Zhu - 我无法在 W7 x64 上的 FF11 中重现该问题。但是,您是否尝试过在事件绑定中使用 event.stopPropagation()?我想知道它是否真的是由于选择框的呈现方式而导致的事件冒泡问题。
2021-05-17 05:55:17

本质上,问题在于创建一个选择菜单,该菜单将在做出选择时触发一个事件,即使它是相同的。

这在技术上这样做的(有点),但在 FF 中,当您单击打开和单击关闭时它会触发(您实际上可以一键完成,这在 Safari 和 Firefox 中产生完全相同的结果)。但这同一个事件。(点击触发触发$('#sel'));

$("#sel").click(function(event) {
    if($(event.target).is('option')) {
        $(this).closest('select').click();
        return true;
    }
    console.log(event.target);
});

我说它“有点”这样做的原因是,如果您从选项卡上选择下拉列表并使用箭头键,它就无法处理。我认为,如果即使选择了事件相同的项目,也需要触发事件,则需要以不同的方式进行处理。对于作为开发人员的我来说,如果这是我的项目,如果我使用 Tab 键切换到一个选择框并选择一个项目而不触摸鼠标,它将无法工作(这意味着如果用户来到我的网站并进行交互)有一个没有鼠标的选择框,它不做他甚至不知道它应该做的事情,可能会使整个事情不起作用,等等)。

我们可以在上班的路上玩一整天.click(),但这并不是真正的解决方案,即使我们实现了最初的目标。(哦,我永远无法在 Chrome 中触发任何东西)。

就像我在评论中所说的那样,我认为这与他们如何处理与选择的交互有关。几乎感觉好像 Safari 的选择实际上并不在页面上......它排序创建了这个漂亮的元素,<option>当你点击它时,它的行为和看起来像一个元素列表,但事实并非如此。可能是为什么当您第一次单击它时它也不会触发。当您单击它时,Webkit 不会将其视为“真实”元素,而只会在您关闭它时触发单击选择,而从未与“真实”选项进行交互。

更改 HTML 可能是唯一的方法(就像 Chosen 所做的那样)。具有讽刺意味的是,某些已选择的元素(看起来像下拉列表的元素)无法通过 Tab 键来选择……至少在他们的演示页面上不能(请参阅“标准选择”)。但这至少迫使我点击它,所以它会触发与鼠标相关的事件。

反正,我恨未解决的问题,但它看起来像有一个为没有得到真正的解决办法.click(),以工作在<select>所有的浏览器,我们应该开始关注替代解决方案。对不起 :-(