from -- 点我
<div>
<button>123</button>
</div>
<script>
var div = document.querySelector('div');
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log('bubble', 'btn');
}, false);
btn.addEventListener('click', function() {
console.log('capture', 'btn');
}, true);
div.addEventListener('click', function() {
console.log('bubble', 'div');
}, false);
div.addEventListener('click', function() {
console.log('capture', 'div');
}, true);
</script>先不看结果,思考一下。
capture div
bubble btn
capture btn
bubble div
非也非也!
- csdn
- 掘金
于是作者决定给 chromium 报 bug~
最终在 Chrome 开发人员的帮助下,找到了这两个讨论
起因是在 https://bugs.webkit.org/show_bug.cgi?id=174288 中,有人指出,在 webkit 中当前的事件模型,会导致含有 Shadow DOM 的情况下,子元素的捕获事件会优先于父元素的捕获事件触发。
而在旧模型中,一旦达到 AT_TARGET ,所有注册的监听器就将按照顺序被触发,而不管他们是否被标记为捕获。由于 Shadow DOM 会创建多个 targets ,导致了事件执行顺序的错误。
而上述问题在 Gecko (Mozilla Firefox 的排版引擎)却运行正常(先捕获再冒泡)。为此 whatwg 提出了一个新的模型结构来解决这个问题。
| 1.按照旧版本事件触发机制 | |
|---|---|
| 表现 | 目标元素触发事件顺序和注册事件顺序有关 |
| 2.新的的事件触发机制 | |
| 表现 | 目标元素触发事件顺序按照先捕获再冒泡的顺序触发 |
而这个版本分界线是在 Chrome 89.0.4363.0 和 89.0.4358.0。
在 Chrome 89.0.4363.0 以及之后版本中,目标元素的触发事件顺序不再按照注册顺序触发!而是按照先捕获再冒泡的形式依次执行!
我们只需要将所有目标元素代码的顺序都按照先书写捕获事件代码,再书写冒泡事件代码,就可以兼容本次的更新。
所有的事情都不是一成不变的,不管是对于一些相对官方的文章或者教程我们都要抱以怀疑的态度,相信我们所看到的。也许我这篇的言论在多年之后也会是一个错误示例,但是是对当下问题的一个记录。本文也还有很多不足之处,如果有问题请在评论中指出。
这文章让我想起之前碰到过类似的异步执行顺序问题。
async function async1(){
await async2()
console.log('async1 end')
}
async function async2(){}
async1();
new Promise(function(resolve){
resolve();
}).then(function(){
console.log('promise2')
}).then(function() {
console.log('promise3')
}).then(function() {
console.log('promise4')
})在 chrome canary 73 返回
async1 end
promise2
promise3
promise4
而在 chrome 70 上返回
promise2
promise3
async1 end
promise4
这道题其实问的是
await async2()怎么理解?
因为 async 函数总是返回一个 promise,所以其实就是在问
await promise怎么理解?
在此不深究,有兴趣的话可以查阅以下参考资料~
- https://segmentfault.com/q/1010000016147496
- https://www.zhihu.com/question/268007969/answer/339811998
- https://juejin.cn/post/6844903715342647310
- https://devblogs.microsoft.com/typescript/announcing-typescript-4-3-rc/
- https://www.oschina.net/news/141604/typescript-4-3-rc-released
视频 + PPT 放出!
Webpack无疑是目前最受欢迎的前端项目的打包和构建工具,目前也达到了第五个大版本,包含了非常多的功能。
然而,在以下场景中,Webpack已经不是最好的打包构建工具:
- Dev模式下的构建速度
- 非常简单的配置文件
- Bundle文件大小
针对上述几个问题,社区有一些其他可使用的替换工具,如Parcel、Rollup、Vite和Snowpack等。
所以,在以后的项目构建技术方案选型时,可以多考虑一下你的使用场景,是否真的应该还使用Webpack?
文中介绍了关于img标签相关的两个东西:alt属性和figcaption标签。
alt属性,大家应该都不陌生,它是图片资源的一个描述信息,且只在图片加载失败的情况下才会显示出来,以应对这些异常情况和支持Accessibility的场景(它的内容会被阅读器读出来)。
而figcaption标签不太一样,它也是表示对图片内容的描述,只不过它需要被figure标签包裹,且内容会一直显示页面中。文中给出了一些这两个特性的使用场景介绍和示例代码,可以帮助你更好地理解它们。
我们现在在网上(尤其是中文搜索环境中)获取到的关于活跃对象和可变对象(Variable Object)的文章,大多都是为我们描述的 ECMAScript 1 和 3,早已过时。
在 ES5 及之后的 ES 版本,已经不存在活跃对象(AO)及一系列周边内容的概念了。取而代之,是一个叫词法环境(Lexical Environments)的定义。
我们现在再聊起活跃对象时,应该知道它只是广义的抽象,而不再是狭义的定义了。广义的活跃对象在不同的场景下也可以有不同的名字,如活跃记录(Activation Record)、栈帧(Stack Frame)等。
zx是一个JavaScript生态下的工具,它可以让你通过JavaScript调用并执行bash命令,用法还比较简单直观。
#!/usr/bin/env zx
await $`cat package.json | grep name`
let branch = await $`git branch --show-current`
await $`dep deploy --branch=${branch}`
await Promise.all([
$`sleep 1; echo 1`,
$`sleep 2; echo 2`,
$`sleep 3; echo 3`,
])
let name = 'foo bar'
await $`mkdir /tmp/${name}`通常我们要判断某一年是否是闰年,需要掌握闰年的定义规则,并按照该负责的规则来判断。下面介绍一个通过反推来判断是否是闰年的方法。
function isLeapYear(year: number) {
return new Date(year, 1, 29).getDate() === 29
}
export default isLeapYear