记录工作时遇到的一些问题。
创建自定义事件
https://developer.mozilla.org/zh-CN/docs/Web/Guide/Events/Creating_and_triggering_events
var event = new Event('build'); |
判断字符串起始
String.prototype.startsWith() |
简单的任务队列
this.queue = Promise.resolve(true); |
package.json 私有包处理
"project": "git+ssh://git@github.com/<username>/<proejct>#<branch/commit>", |
安装mecab
brew install mecab |
flex 子元素无法设置为 position sticky
flex 默认 子元素为 strech
设置该子元素 align-self: flex-start;
useEffect / useLayoutEffect 区别
https://juejin.im/post/5de38c76e51d455f9b335eff
文本一行时 居中对齐, 多行时左对齐
<div> // 父元素设置 text-align center |
React、Vue 事件 异步方法使用事件 (合成事件)
// https://zh-hans.reactjs.org/docs/events.html |
对象扩展 条件赋值
{ |
React 报无限 loop
onClick={fun()} |
React Hook 翻页
const [current, setCurrent] = useState(1) |
React Hook 倒计时
useEffect 形成闭包,使用 Ref 存储上次time
或使用 time 作为监听值 触发timeout 成为 interval 来使用
字符问题
转为 Unicode, 可能带有换行 或者特殊字符 ,使用 normalize 转换
? / ?? 的使用
a?.b?.c = 'xxx' |
React Hook 异步引用 state
根本原因 Hook 是向函数中传入函数,形成闭包。
所记录的的函数创建时的引用值,而无法获取更新后(内存地址变化)的值,导致运行异常。
使用 useRef 获得一个,引用类型的变量记录值的变化即可。
之前遇到的一个问题:
// stateA stateB |
有2个页面有会在载入时进行init, 后调用 initCallback 会根据 state 状态跳出,防止重复 init。
但是打log可以发现还是重复init了。 原因还是在于异步调用,虽然 dep 是注册了 initcallback 的变化,但是在执行异步方法中所使用的并不是更新后的 callback,从而使用了错误的 init 状态,导致多次 init。
解决办法是在记录 init state 的同时,使用ref或普通变量去记录且用于判断init状态即可。
drag api
dom 元素在 drag end 时,默认会有一个元素恢复原位的一个动画。
// https://stackoverflow.com/questions/32206010/disable-animation-for-drag-and-drop-chrome-safari |
drag api 兼容
桌面端与移动端不兼容,js只有桌面端(鼠标输入)形式的 drag api.
移动端可使用 https://github.com/timruffles/mobile-drag-drop 做兼容
在既有鼠标输入又有触摸输入的设备(可触屏的win10),无法使用触摸拖拽
自定义 font 顺序加载
使用自定义字体时,如果使用的是外部资源,会出现文字由默认字体到目标字体闪烁变化的问题
// https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face |
字体文件转为 base64 保证加载顺序
或者
<link rel="preload" href="https://fonts.woff2" as="font" crossorigin="anonymous"/> |
IOS 视频不显示封面
IOS设备默认不显示 video 封面有一个有意思的方法
// https://muffinman.io/blog/hack-for-ios-safari-to-display-html-video-thumbnail/ |
IOS 文件下载
IOS中文件下载,js创建的a标签需要append到body中,不然是下载不了的!!
safari 浏览器 url hash 设置有节流限制
出现在使用某个md标题插件,记录当前的位置,过多触发 set url hash, 导致该功能被限制在 30s/次
webpack 打包时记录版本信息
// webpack config |
复合组件
// https://github.com/penouc/blog/issues/7 |
组件数据 部分解耦
// 传入children为函数即可, children 渲染,部分依赖父组件,部分依赖该组件内部数据 |
before / after 伪元素
input 没有伪元素!!!
PWA 更新
// https://create-react-app.dev/docs/making-a-progressive-web-app/
This means that users will end up seeing older content until they close (reloading is not enough) their existing, open tabs. See this blog post for more details about this behavior.
在资源更新的事件触发后,需要关闭tab,再重新打开才能确保资源成功更新
一种有意思设置默认参数形式
当时也不知道怎么想的, 写个这个挺高效的传参方式
const getEvents = ({page_num}={}) => |
Typescript 联合类型断言
data.forEach(item => { |
react function children
适合我这样的懒人
// array children 需要一个 key 哦 |
webthing 设备卡片 UI 模板的设计
第一版
考虑到数据与模板尽量解耦
useBaseThing 可以单独使用,用于注册事件等不需要 UI 参与的业务,
const useBaseThing = (thingDesc) => { |
第二版
第一版虽然完全分离, 但是有个问题,要使用模板就必然要先 useBaseThing 获取数据
所以考虑重构,将模板创建整合进 useBaseThing
同时一个 thing UI 中,需要自定义的部分需要包含更多的内容,如二级对话框、图标、触发按钮等,还要考虑到后期的扩展性,仅留下一个 ThingTemplate children 作为自定义元素就远远不够了。
const useBaseThing = ({ |
thing UI 也通过 useBaseThing 创建,可以根据 templateConfig,设置 UI 是否创建
第三版
目前实际开发下来第二版在扩展性上基本没有什么问题,但感觉还是有一些繁琐了
要说有问题,就是 ThingTemplate 是在 useBaseThing 内部创建,内部的插槽模板是写在外部,传入 useBaseThing, 写起来有一点违和
但是这些 Component 都是依赖 useBaseThing 内部的 state 数据,又没有办法,只能在这个上下文创建。
也许应该还有更加高效的组合方式
input 输入法问题
https://developer.mozilla.org/zh-CN/docs/Web/Events/compositionstart
https://juejin.cn/post/6844903950634713096
text input onchange 事件获取的 value,会包含输入法输入的内容
使用 onCompositionStart 记录当前是否为输入法状态,控制onchange执行
react v17
https://reactjs.org/blog/2020/08/10/react-v17-rc.html#effect-cleanup-timing
组件卸载时 useEffect 的 return 会异步执行,也就是在完全卸载后执行,dom元素事件监听的卸载需要在useLayoutEffect处理
总结就是 useEffect -> 加载 -> useLayoutEffect -> useLayoutEffect -> 卸载 -> useEffect
Electron index.html 加载本地(static)静态 js
旧版本可以这么用
<script src="./static/xxx.js"></script> |
后来为了适配CI升了下版本,过不了打包流程,只能使用一个歪门邪道处理
<script id="syncload"> |
屏幕 / Canvs录制
https://developer.mozilla.org/zh-CN/docs/Web/API/MediaRecorder
https://developer.mozilla.org/zh-CN/docs/Web/API/Screen_Capture_API/Using_Screen_Capture
元素滚动检测 API
createDocumentFragment
可以理解为 React 中的 Fragment, 一个无父节点的元素
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createDocumentFragment
DocumentFragments 是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。在DOM树中,文档片段被其所有的子元素所代替。
因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(对元素位置和几何上的计算)。因此,使用文档片段通常会带来更好的性能。
Webpack 记录版本 plugin
https://github.com/LLK/scratch-www/blob/develop/webpack.config.js#L31
网页水印
https://www.zhangxinxu.com/wordpress/2020/10/text-as-css-background-image/
使用文本 svg 作为元素背景
可以实现类似 before/after 伪元素的效果
网页自动检测黑暗模式
- 使用 CSS 媒体查询可以解决
@media (prefers-color-scheme: dark) { |
https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media/prefers-color-scheme
https://www.zhangxinxu.com/wordpress/2020/11/css-mix-blend-mode-filter-dark-theme/
- 使用 JS
window.matchMedia(“(prefers-color-scheme: dark)”).matches;
Module not found: Error: Can’t resolve ‘fs’
处理一些包
webpack config:
```JSON
{
node: {
fs: 'empty'
}
}
// Webpack >= 5
module.exports = {
...
resolve: {
fallback: {
"fs": false
},
}
}