怎么写高效的css
https://thenextweb.com/news/writing-efficient-css-understand-your-selectors
https://programmerinnervoice.wordpress.com/2013/12/18/how-does-browser-read-css-selector/
https://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-leftt
Don’t Use Inline-Styles
Avoid the !important tag
https://www.freecodecamp.org/news/7-important-tips-for-writing-better-css/
https://csswizardry.com/2011/09/writing-efficient-css-selectors/
ES2020/2021
背景
今天看阮老师的科技周刊的时候,里头提到了ES2021(作者默认所有的提案最终都会被通过),正好借此梳理一下,ES2020和ES2021,个人使用过的以及后续可能会使用的一些功能,所以这篇不是科普类型,纯属个人喜好的记录。
开始
空值合并运算符:??
**??**是一个逻辑操作符,当左侧的操作数为
null或者undefined时,则返回右侧操作数,否则返回左侧操作数。所以该运算符完美适配默认值的场景。
1 | const foo = null ?? 'default string'; |
多说一句:
设置默认值以前常用的是:**||**(逻辑或操作符),但是都知道不用用它作为有false和0的情况(因为||**判断时,会把值转换为布尔值,而false和0转为布尔值时都是false,所以对于数字类型和布尔类型的用||设置默认值是不合理的+)
可选的链接运算符:?.
嵌套对象时特别好用。表达式还短。
如果引用为空(null 或 undefined),则表达式会短路返回 undefined。
1 |
|
Promise.any() and AggregateError
Promise.any()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态
阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版
Promise.any()跟Promise.race()方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而结束。
1 | Promise.race([ |
globalThis
全局属性 globalThis 包含全局的 this 值,类似于全局对象(global object)。globalThis 提供了一个标准的方式来获取不同环境下的全局 this 对象(也就是全局对象自身)不用在考虑不同的环境获取方式不一样的问题。
String replaceAll()
1 | const newStr = str.replaceAll(regexp|substr, newSubstr|function). |
replaceAll(pattern,replacement) 方法返回一个新字符串,新字符串所有满足 pattern 的部分都已被replacement 替换。pattern可以是一个字符串或一个 RegExp, replacement可以是一个字符串或一个在每次匹配被调用的函数。
old:
1 | const str = "zhangsan is wangmazi's 舅子,wangmazi is zhangsan's 妹夫"; |
new:
1 | const str = "zhangsan is wangmazi's 舅子,wangmazi is zhangsan's 妹夫"; |
逻辑赋值运算符:(&&= ||= ??=)
1 | x ||= y; |
下划线作为数字分隔符
1 | const billion = 1000_000_000; |
Promise.allSettled
我通常在页面初始化需要多个数据且相互之间又没联系的时候会用它。
**Promise.allSettled()**方法接受一组Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果(不管是
fulfilled还是rejected),返回结果是一个对象数组,每个对象表示对应的promise结果。当有多个彼此不依赖的异步任务成功完成时,或者我们不关心异步操作的结果,只关心每个
promise的结果时,通常使用它。
1 | const p1 = new Promise((resolve, reject) => setTimeout(resolve, 1000,'failed')); |
相比之下,
Promise.all()更适合彼此相互依赖或者在其中任何一个reject时就需要立即结束的场景。即Promise.all()其实无法确定所有请求都结束。
参考资料:
https://github.com/tc39/ecma262/releases
https://backbencher.dev/javascript/es2021-new-features
https://tc39.es/ecma262/2021/#sec-web-scripting
https://www.telerik.com/blogs/learn-new-features-introduced-javascript-es2021
https://blog.fundebug.com/2019/08/28/javascript-nullish-coalescing/
本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。
You're worrying about the wrong thing if you're trying to learn it all
别想着记住所有东西
https://www.kevinpowell.co/article/youre-worrying-about-the-wrong-things/
https://www.youtube.com/watch?v=vP2MNhC_Igw
为了成为一名前端开发人员,我们需要学习一百万零一件事,似乎每 30 秒就有另一件新东西需要我们添加到我们的武器库中。
学习新事物可能很有趣,但是当我们需要学习的新事物清单似乎不断增加时,它可能会让人不知所措。
还有一个大问题。当我们离开学习所有这些新东西时,我们他妈的怎么能记住我们已经学过的所有东西?
我经常被问到,通过 DM 或来自追随者的电子邮件,或者有时作为 YouTube 评论,询问记住所有内容的最佳策略。
事实是,我什么都不记得。我记得一些东西是因为我一直在使用它们,并且因为我主要关注 CSS。我使用它们的次数越多,与它们相处得越好,与它们相处的乐趣也就越多。但我不记得一切。
事实上,它甚至不接近。
这都是一个大谎言
当您观看我的 YouTube 视频或其他人编写代码时,似乎我无所不知。然后下周我发布了一个关于新主题的新视频,我也知道!
我当然是了!我已经把它写好了,而且我之前已经建立了那个东西。
大多数情况下,有关编码的视频和课程中的人们只是从其他屏幕上的已完成版本中复制代码。
事情需要计划好!否则,课程的质量将很糟糕。
但它确实给人一种错误的感觉,即那里的“专业人士”知道并记住一切。
没有人记得这一切
我喜欢听关于开发的播客的原因之一是当你仰望的人谈论他们是如何忘记事情的时候,或者不得不查找事情的时候(有时是我非常了解的事情!)。
不断在ShopTalk Show 上,他们的名字出现了,我非常尊重,他们谈论他们如何必须为他们写的一本书研究某些东西,然后发现自己不得不阅读他们自己书中的部分内容记住它是如何工作的。
我可以理解这一点,我确实看过我自己视频的一部分来记住如何做某些事情。
我知道这是我以前知道的东西(毕竟我确实制作了一个视频!),但是因为我有一段时间没有使用那个东西了,也许即使我制作了那个视频,我也不记得到底是怎么回事它不再起作用了!
这是正常的。
而且我认为重要的是要知道我们不应该记住所有内容。
这不是要记住所有内容,而是要知道解决方案存在
CSS 中有很多小技巧和窍门,很多很酷的小功能,我无法记住它们是如何工作的,或者说,它们甚至都叫什么!
但是出现了一些事情,而不是想“嗯,我不知道我可以在这里做什么”,而是“哦,我知道有这个东西可以帮助解决这个问题”,然后我立即研究它是什么。也许这是我看到一篇文章或视频的东西,或者也许是我过去使用过的东西,只是忘记了它是如何工作的。
这不是要记住一切是如何运作的。你永远不会那样做。相反,它是关于知道解决方案存在。
你做的事情越多,你越需要使用这些晦涩的功能,你就越会记住它们是如何工作的。然后你将不会使用它 6 个月,你会完全忘记。
这很好。
开源软件的版本
这两天不是React 18[1] duang的一下炸了吗?刚好在了解的过程中看到了React工作组的发布计划[2]
个人觉得是写的很清晰,把不同阶级的版本都进行了说明,在这儿简单说一下每种版本代号的含义。
Apha
内部测试版,主要是针对社区内部人员发布的。α是希腊字母的第一个,表示最早的版本,一般不建议下载这个版本,这个版本包含很多BUG,功能也不全,因为主要是给开发人员和测试人员测试和找BUG用的。
Beta
公开测试版。β是希腊字母的第二个,顾名思义,这个版本在alpha版之后,主要是给一些相关的社区以及忠实的用户测试用的,该版将包含最终版本的所有重大更改和新功能,但是仍然存在一些未发现的BUG,但是相对alpha版要稳定一些。所以还是为了收到反馈并发现任何遗留问题。
如果是负责基础能力的代码大哥们,实在着急的可以开始使用这个版本,主要是测试一下新功能以及升级方面的问题,提前入场准备。
RC
Release Candidate(候选版本),该版本不会再有新增的功能,所以是最接近最终版的版本。该版本的功能已经比较完整和稳定,rc的发布标志着最终版即将到来,rc主要是收集一下版本的稳定性以及用户满意度方面的数据。
这个版本其实一般用户可以下场练手了。
Stable
稳定版。这个就是最终发行版,你可以在里面遨游了。
References
[1] React 18 介绍: https://github.com/reactwg/react-18/discussions/4[2] React 18发布计划: https://github.com/reactwg/react-18/discussions/9
page-lifecycle-api
背景
最近又把前端监控的兴趣提了起来,学习过程中了解到了google的page-lifecycle-api,特此做个记录撒。
https://developers.google.com/web/updates/2018/07/page-lifecycle-api
npm版本锁定
背景
源起于同事找我帮忙排查一个认为诡异的问题。
同样的代码,同样的package.json本地和流水线部署效果不一样。问我可能是什么原因,我当时想到的可能就两种情况:
- 依赖包的版本不一样
- 流水线本身存在问题,比如没有拉到最新的代码?
我简单提供用排除法的思路让她走了一遍,排除了不是最新代码的问题,然后让其对比了一下pacage-lock.json文件,的确发现了依赖包的版本变了,当手动在package.json锁死了本地使用的版本号之后,再执行部署则没有问题。
所以最终问题出在package-lock.json上,那为什么package-lock.json每次跑流水线的时候都会变化呢,是因为流水线脚本里部署前端时脚本里会有:
1.npm clean
2.rm- rf node_modules
3.npm i …等步骤
所以导致每次会更新package-lock.json,那我们提交的package-lock.json就失去了它的价值,即可能每次CI都会有不同版本的包依赖。
经过这次的排查,遂记录一下锁包的个人理解。
开始
package-lock.json
npm 关于package-lock.json的解释说的挺清楚了。主要作用锁定(描述)包依赖关系及其子依赖项。保证对其他开发人员或其他环境安装包的依赖关系一致。
如图:eslint-plugin-react依赖树
修改node_modules或package.json将自动生成package-lock.json。 它描述了包版本的依赖树,使得后续可以保证无论在哪儿安装能够生成相同的依赖树(也就是相同的包版本),而不管中间依赖性更新如何。
每当我们运行更改依赖项的NPM命令时,如npm i
或npm uninstall 或npm i 等,都将更新包锁定即更新package-lock.json文件。 所以每次提交时必须把package-lock.json也提交到git。
执行npm i 时会读取根据package.json创建的依赖项列表,并使用package-lock.json来通知哪些版本的这些依赖项需要安装。 如果依赖项不在package-lock.json中,它将通过npm i 添加。
根据上面总结的信息,我理解解决上述问题的其中一个方案就是每次CI的时候只需要拉代码之后再npm i 即可,从而保持依赖一致。
npm ci
在深入了解package-lock.json的过程中,npm ci进入了我的视线,详见npm ci。
npm ci(ci:持续集成)直接从package-lock.json安装依赖关系,并使用package.json验证是否存在不匹配的版本。 如果缺少任何依赖项或具有不兼容的版本,则会抛出错误。
因为npm ci是基于package-lock.json进行安装,所以就体现了该命令在包一致性上的作用,在需要重复构建、持续集成等场景下好用。
前提:
必须有package-lock.json文件,即项目第一次初始安装时不能用npm ci,这也说明了为什么上面章节谈到package-lock.json也需要提交到git,这也是原因之一。
所以另一个方案就是每次CI的时候只需要拉代码之后再npm ci 即可,也可保持依赖一致(前提是package.json、package-lock.json每次都进行了同步提交)。
npm i vs npm ci
- npm ci不会更新package-lock.json和package.json,即npm ci 不能更新依赖。
- npm ci必须基于package-lock.json。
- 一般情况下npm ci安装速度会更快。npm ci时如果存在node_modules则会先删除node_modules。
- 初始安装以及更新依赖时,只能使用npm i。
另一个问题:咋个解决package-lock.json冲突
这是一个延申出来的问题,因为需要提交package-lock.json,由于一些原因就可能出现冲突的情况,那咋解决呢?
- 最好别上来就先删除package-lock.json,人是自动生成的没必要跟它较劲。从基线上拉一个package-lock.json文件下来。
- 处理package.json的冲突。
- 执行npm i。
参考:
本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。
The Clean Architecture
缩小差距
背景
有些膨胀了,看到了一篇介绍《缩小差距》书的文章,准备对OKR、KPI等企业考核机制做进一步了解,说不定有一天我就平步青云了呢不小心搞个世界500强的管理者当当,到时候可以参考这用用。在这儿做个记录。
前面还是开玩笑的,主要还是身为被考核者,想更深入的了解考核背后的一些东西。虽然内容看上去是从和消费者(顾客)角度来谈绩效,不过我认为其实可以套在公司内部技术团队里,比如上下级对应消费者与服务者的视角?或者反过来?
开始
组织内的各级管理者经常会发现问题,并直接跳到解决方案里去。很多时候,这些方案并不能解决任何问题,这是因为管理者没有找到问题的根本原因。《缩小差距》这本书展现了一个近乎完美的模式,提供一个 无懈可击的思路。你会发现,探究深藏在”现实状况”和”应有水平” 之间差距的原因,是打开最佳解决方案的钥匙。
其实这段内容不太符合我们公司,不是拍马屁,我们公司的管理层最不喜欢直接跳到解决方案里去,平常传递给我们的信息,先找根因,我之前的文章有写。
书中有个高频词语GAPS。
GAPS
GAPS不仅仅是一种模式和策略,它更代表一种全新的企业哲学。把它融入你的管理,你会发现一切变得水到渠成。
决定一个组织成败与否的一个至关重要因素就是人员的绩效。 这里所说的人员包括:工作者、决策者以及与顾客相互接触的人。如果他们能够高质量地完成工作,做出正确的决策,很好地对待顾客,组织就有机会生存,并且有可能兴 旺发达。
有许多因素包括组织的外部和内部因素一一影响人员的绩效。这些因素中,有些具有可控性,有些则是不可控的。
《缩小差距》就是关于如何管理那些可控性因素的。它的主要内容是:如何找到那些对人的工作绩效具有消极影响的因素,并且消除它们。同时,《缩小差距》的内容还包括;用系统的方法揭露并纠正这些因素,以使最 终的影响变得有意义,并且可测量。
每个人的生命中都会有许多美妙的时刻,所有这些时刻,更多的时候,是一种完美。完美是因为,在”现实 状况”和”应有水平”之间没有差距。
在今天飞速变化的商业环境中,管理者在面对问题时,通常是 在没有考虑问题的真正核心的情况下“直接跳到解决方案”。本书将 通过帮助组织中任何层次的人理解”差距战略”并把它应用于工作中, 从而使他们能够避免陷人那些具有破坏性的陷阱。
chapter 1
商业需要=>绩效需要,绩效需要=>工作环境和能力需要。换句话说,你们公司的客户服务代表应该以怎样更多、更好、更与众不同的行动来帮助你实现商业目的。”
朝〃应有水平’’前进
始终是”更多、更好、更不同” 上
向”应有水平”看齐
向”应有水平”前进
“你得确定’应有水平’是什么。’应 有水平’是你首要的焦点问题,必须为之努力。现在看来,你有两个 ‘应有水平’,
第一个就是我听你说的定额标准:确定标准
第二种是行为的’应有水平:什么是需要做得更多、更好或 更不同的,期望得行为。
做,还是不做
- 问可以自由回答的问题,收集有关消费者故障的信息
- 注意聆听,并且抓住问题的实质
- 基于消费者的情绪或感觉来调整对方的反应
- 在语气上不要表现出争论性,也不要具有攻击性或辩护性
- 在交谈的过程中经常提到顾客的名字
- 看出顾客期望从公司里得到什么,明确说明公司将要采取的行 动
- 提供一个解决问题的切实可行的时间期限
- 表现出耐心并且允许顾客发泄情绪
- 引导交谈重新回到正题轨道上,以缩短整个谈话的长度
- 为任何一个客户服务代表或公司的错误道歉
现实就是差距
目前我们在做的每一件事就 相当于”现实状况” “现实状况”就是差距所在! 分析”现实状况”!
你们不该直接跳到解决方案。相反,你要做的是,比较”现实状况’中的工作 绩效和。应有水平’中的工作绩效,以确定差距所在。”
造成差距的原因
缺少的部分
“这件事用简单的四个字就可以概括:弄清原因。你永远不能、也不可能直接跳到解决方案,你得挖掘原因。很多时候,它们不会直接表露在面上。而是深藏在表皮之下。”
从某些方面来说, 是原因约束了我们。我们曾为了解决问题而苦苦奋斗,而不从实际上 挖掘根本的原因。我们知道了’应有水平’应该是什么样的,并且要组织中心团队来揭露和分析”现实状况”,但是我们却没有弄清楚原因来消除差距。”
对正确的人以正确的方式问正确的问题,你就能够分析’现实状况’并弄清原因。你会很好地缩短’应有水平’和’现实状况’之间的差距。
从原因到解决方案
本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。
React Hooks(二)
https://medium.com/geekculture/useimperativehandle-by-examples-99cbdc8e3c3a
Allow me to preface this answer by stating that all of these hooks are very rarely used. 99% of the time, you won’t need these. They are only meant to cover some rare corner-case scenarios.
useImperativeHandle
Usually when you use useRef you are given the instance value of the component the ref is attached to. This allows you to interact with the DOM element directly.
useImperativeHandle is very similar, but it lets you do two things:
It gives you control over the value that is returned. Instead of returning the instance element, you explicitly state what the return value will be (see snippet below).
It allows you to replace native functions (such as blur, focus, etc) with functions of your own, thus allowing side-effects to the normal behavior, or a different behavior altogether. Though, you can call the function whatever you like.
There could be many reasons you want might to do either of the above; you might not want to expose native properties to the parent or maybe you want to change the behavior of a native function. There could be many reasons. However, useImperativeHandle is rarely used.
useImperativeHandle customizes the instance value that is exposed to parent components when using ref
Example
In this example, the value we’ll get from the ref will only contain the function blur which we declared in our useImperativeHandle. It will not contain any other properties (I am logging the value to demonstrate this). The function itself is also “customized” to behave differently than what you’d normally expect. Here, it sets document.title and blurs the input when blur is invoked.
Show code snippet
useLayoutEffect
While similar to some extent to useEffect(), it differs in that it will run after React has committed updates to the DOM. Used in rare cases when you need to calculate the distance between elements after an update or do other post-update calculations / side-effects.
The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
Example
Suppose you have a absolutely positioned element whose height might vary and you want to position another div beneath it. You could use getBoundingCLientRect() to calculate the parent’s height and top properties and then just apply those to the top property of the child.
Here you would want to use useLayoutEffect rather than useEffect. See why in the examples below:
With useEffect: (notice the jumpy behavior)
Show code snippet
With useLayoutEffect:
Show code snippet
useDebugValue
Sometimes you might want to debug certain values or properties, but doing so might require expensive operations which might impact performance.
useDebugValue is only called when the React DevTools are open and the related hook is inspected, preventing any impact on performance.
useDebugValue can be used to display a label for custom hooks in React DevTools.
I have personally never used this hook though. Maybe someone in the comments can give some insight with a good example.