为什么在点击事件侦听器中触发 click() 不会导致无限循环?
Why doesn't triggering click() inside a click event listener cause an infinite loop?
谁能解释一下这个JavaScript代码的程序流程:
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a);
console.log("check");
a++;
$leaveRoom.click();
console.log(a);
a++;
});
<button id="leave-button">Leave Room</button>
The Output was:
1
check
2
check
3
4
这个问题听起来可能很愚蠢,但我是 JavaScript 的新手。我无法理解这段代码的程序流程。我想知道我是如何在输出中得到 3 和 4 的。
The key to this question is the presence of a hidden Flag on each element.click()
method.
Each element has an associated click in progress flag, which is initially unset.
文档:https://html.spec.whatwg.org/multipage/interaction.html#dom-click
只要这个方法被激活,这个flag就会从progess Status == unset
变成progess Status == active
(伪代码)
(然后它 returns 到它包含的代码完全执行后的初始状态)
当此标志处于 active
状态时,将忽略对该方法的任何调用。
这是我原来的 post 来显示 `console.log()` 的执行顺序
const bt_leaveRoom = document.querySelector('#leave-button')
var counter = 0
var origin = 'event clic'
bt_leaveRoom.addEventListener('click', () =>
{
let source = origin
console.log(`_first console.log(): counter = ${ ++counter }, origin = ${source}`)
origin = 'call'
bt_leaveRoom.click()
console.log(`second console.log(): counter = ${ ++counter }, origin = ${source}`)
})
<button id="leave-button">Leave Room</button>
如果我这样编码,Hidden Flag 的作用与此相同:
替换此行:
bt_leaveRoom.click()
至:
if (source !== 'call') bt_leaveRoom.click()
但实际上系统使用隐藏标志的方法(名为progress flag
?)
可以是(伪代码)
if (progress_flag_of_bt_leaveRoom.click() is unset) do { bt_leaveRoom.click() }
我尝试了几件事来找到这个问题的答案。对于这里发生的事情,我还没有真正找到明确的答案,但我相信我在这里分享的内容会解决这个极好的问题。
我简化了代码以专注于事件的递归触发。
简化代码
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
$leaveRoom.click();
});
<button id="leave-button">Leave Room</button>
我们可以在这里看到我们有两个调用 console.log
,第一个是实际点击按钮,第二个是对 $leaveRoom.click();
的调用。它似乎因某种原因停在那里。
使用dispatchEvent
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
$leaveRoom.dispatchEvent(new Event('click'));
});
<button id="leave-button">Leave Room</button>
这里,事件被触发了多次(我是 44 次),这可能是因为你的机器速度太快了。它似乎最终停止触发,所以我认为同样的现象也发生在这里。
使用setTimeout
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
setTimeout(() => { $leaveRoom.click(); });
});
<button id="leave-button">Leave Room</button>
如果您正在寻找一种无限触发点击事件的方法,而不管之前的方法为何失败。这似乎确实可以解决问题。
说了这么多,我仍然不知道这种阻止以前方法递归的隐藏力量。也许有人可以阐明这一点。
const click1 = document.querySelector('#click1')
const click2 = document.querySelector('#click2')
const click3 = document.querySelector('#click3')
click1.addEventListener('click', (event) => {
console.log("click1")
click2.click()
});
click2.addEventListener('click', (event) => {
console.log("click2")
click3.click()
});
click3.addEventListener('click', (event) => {
console.log("click3")
click1.click()
});
<button id="click1">Click 1</button>
<button id="click2">Click 2</button>
<button id="click3">Click 3</button>
实际上事件处理中似乎存在循环中断逻辑。处理程序将愉快地菊花链用户输入事件,直到初始交互分派重复事件。然后就不再派发了。
谁能解释一下这个JavaScript代码的程序流程:
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a);
console.log("check");
a++;
$leaveRoom.click();
console.log(a);
a++;
});
<button id="leave-button">Leave Room</button>
The Output was:
1
check
2
check
3
4
这个问题听起来可能很愚蠢,但我是 JavaScript 的新手。我无法理解这段代码的程序流程。我想知道我是如何在输出中得到 3 和 4 的。
The key to this question is the presence of a hidden Flag on each
element.click()
method.Each element has an associated click in progress flag, which is initially unset.
文档:https://html.spec.whatwg.org/multipage/interaction.html#dom-click
只要这个方法被激活,这个flag就会从progess Status == unset
变成progess Status == active
(伪代码)
(然后它 returns 到它包含的代码完全执行后的初始状态)
当此标志处于 active
状态时,将忽略对该方法的任何调用。
这是我原来的 post 来显示 `console.log()` 的执行顺序
const bt_leaveRoom = document.querySelector('#leave-button')
var counter = 0
var origin = 'event clic'
bt_leaveRoom.addEventListener('click', () =>
{
let source = origin
console.log(`_first console.log(): counter = ${ ++counter }, origin = ${source}`)
origin = 'call'
bt_leaveRoom.click()
console.log(`second console.log(): counter = ${ ++counter }, origin = ${source}`)
})
<button id="leave-button">Leave Room</button>
如果我这样编码,Hidden Flag 的作用与此相同:
替换此行:
bt_leaveRoom.click()
至:
if (source !== 'call') bt_leaveRoom.click()
但实际上系统使用隐藏标志的方法(名为progress flag
?)
可以是(伪代码)
if (progress_flag_of_bt_leaveRoom.click() is unset) do { bt_leaveRoom.click() }
我尝试了几件事来找到这个问题的答案。对于这里发生的事情,我还没有真正找到明确的答案,但我相信我在这里分享的内容会解决这个极好的问题。
我简化了代码以专注于事件的递归触发。
简化代码
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
$leaveRoom.click();
});
<button id="leave-button">Leave Room</button>
我们可以在这里看到我们有两个调用 console.log
,第一个是实际点击按钮,第二个是对 $leaveRoom.click();
的调用。它似乎因某种原因停在那里。
使用dispatchEvent
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
$leaveRoom.dispatchEvent(new Event('click'));
});
<button id="leave-button">Leave Room</button>
这里,事件被触发了多次(我是 44 次),这可能是因为你的机器速度太快了。它似乎最终停止触发,所以我认为同样的现象也发生在这里。
使用setTimeout
const $leaveRoom = document.querySelector('#leave-button');
let a = 1;
$leaveRoom.addEventListener('click', () => {
console.log(a++);
setTimeout(() => { $leaveRoom.click(); });
});
<button id="leave-button">Leave Room</button>
如果您正在寻找一种无限触发点击事件的方法,而不管之前的方法为何失败。这似乎确实可以解决问题。
说了这么多,我仍然不知道这种阻止以前方法递归的隐藏力量。也许有人可以阐明这一点。
const click1 = document.querySelector('#click1')
const click2 = document.querySelector('#click2')
const click3 = document.querySelector('#click3')
click1.addEventListener('click', (event) => {
console.log("click1")
click2.click()
});
click2.addEventListener('click', (event) => {
console.log("click2")
click3.click()
});
click3.addEventListener('click', (event) => {
console.log("click3")
click1.click()
});
<button id="click1">Click 1</button>
<button id="click2">Click 2</button>
<button id="click3">Click 3</button>
实际上事件处理中似乎存在循环中断逻辑。处理程序将愉快地菊花链用户输入事件,直到初始交互分派重复事件。然后就不再派发了。