为什么我的自定义jQuery `change`事件会被触发两次?

5

我正在尝试制作一个兼容jQuery的组合HTML输入框。

这个例子中,无论哪个select发生变化,alert都会被调用两次。为什么?

给定一个简单的容器节点:

<span id="x"></span>

这里是完全可用的演示:

function el (type) {
    return document .createElement (type);
}

function opt (sel, value) {
    let node = el ('option');
    node .value = value;
    node .appendChild (document .createTextNode (value));
    sel .appendChild (node);
}

let x = document .getElementById ('x');
let a = el ('select');
let b = el ('select');

x .appendChild (a);
x .appendChild (b);

opt (a, 'a_1');
opt (a, 'a_2');
opt (b, 'b_1');
opt (b, 'b_2');

$(a) .change (function () {$(x) .trigger ('change');});
$(b) .change (function () {$(x) .trigger ('change');});

$(x) .change (function () {alert ('changed');});

因为a和b都等于select吗?你是否尝试过使用let b = el('select#b')和let a = el('select#a')? - Timmy Von Heiss
el 创建一个新的元素。 - spraff
2个回答

3

当你改变下拉菜单中的值时,它会改变结构中的父级元素。这意味着当你改变 A 和 B 的值时,它们的父级 X 也会自动更改。因此,你需要停止事件传播。

你需要移除下面的代码:

$(a) .change (function () {$(x) .trigger ('change');});
$(b) .change (function () {$(x) .trigger ('change');});

或者您需要使用preventDefault();

$(a) .change (function (e) {e.preventDefault(); $(x) .trigger ('change'); return false; });
$(b) .change (function (e) {e.preventDefault(); $(x) .trigger ('change'); return false; });

0

onchange事件会冒泡吗?

jQuery文档建议此事件仅适用于输入、选择和文本区域,但无论如何,它都会向父元素传播(冒泡)。

如果停止冒泡,就会起作用:

$(a) .change (function (event) {
    $(x) .trigger ('change');
    console.log('a');
    event.stopPropagation();
});

$(b) .change (function (event) {
    $(x) .trigger ('change');
    console.log('b');
    event.stopPropagation();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接