首页
Search
1
解决visual studio code (vscode)安装时没有选择安装路径问题
321 阅读
2
如何在 Clash for Windows 上配置服务
216 阅读
3
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
150 阅读
4
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
149 阅读
5
uniapp打包app提示通讯录权限问题,如何取消通讯录权限
113 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
1,202
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
765
篇与
的结果
2024-10-20
Can’t perform a React state update on an unmounted component
最近项目中有一个这样的需求,从别的项目要转到我项目中的某个页面,不过回退时要可以回退到项目的首页。实现这样的跳转的话,应当是首先要跳转到项目的首页,然后再从首页跳转到对应的页面。我最开始的实现是这样的:componentDidMount() { const jumpUrlList = ['own']; const jumpUrl = getQueryString('jumpto'); const targetJump = window.sessionStorage && window.sessionStorage.getItem('targetJump'); // 防止无限跳转,使用sessionStorage存储一个标记,整个周期内只跳转一次 if (jumpUrlList.indexOf(jumpUrl) > -1 && !targetJump) { window.location.href = '#/' + jumpUrl; window.sessionStorage.setItem('targetJump', '1'); } } 但运行时,会提示这个错误: Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method. 意思是:无法对没有实例的组件进行响应状态更新。您可以在 componentWillUnmount 方法中取消所有的订阅和异步任务。因为我在首页中有异步请求,请求返回回来后,使用setState更新视图。但我已经跳转到别的路由了,导致 setState 更新时,当前组件已被销毁了,无法更新。解决方法: 若您的异步请求可以取消的话,在 componentWillUnmount 中取消请求; 在render()方法中进行判断,若可以跳转,则直接不渲染; render() { const jumpUrlList = ['own']; const jumpUrl = getQueryString('jumpto'); const targetJump = window.sessionStorage && window.sessionStorage.getItem('targetJump'); if (jumpUrlList.indexOf(jumpUrl) > -1 && !targetJump) { window.location.href = '#/' + jumpUrl; window.sessionStorage.setItem('targetJump', '1'); return null; } return ( ); } 使用高阶组件重新封装 componentWillUnmount 和 setState; function inject_unount(target) { // 改装componentWillUnmount,销毁的时候记录一下 let next = target.prototype.componentWillUnmount; target.prototype.componentWillUnmount = function() { if (next) next.call(this, ...arguments); this.unmount = true; }; // 对setState的改装,setState查看目前是否已经销毁 let setState = target.prototype.setState; target.prototype.setState = function() { if (this.unmount) return; setState.call(this, ...arguments); }; } @inject_unount class BaseComponent extends Component {} //以后我们写组件时直接继承BaseComponent
2024年10月20日
7 阅读
0 评论
0 点赞
2024-10-20
如何减少函数参数的输入
前几天在某论坛上看的一个问题,实际上这问题并不难,如何减少函数参数的输入,目前可以用两种方法来实现: 柯里化:把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数; 解构:基于ES6的变量解构 1. 柯里化 # 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数。比如有一个数据上报的函数A,在多次调用这个函数A时,有两个参数是固定的,这样我使用柯里化的原理来优先输入这两个固定的参数:// bossid和pwd为数据必须的参数 // page为当前页面 // act为操作 function funcA(bossId, pwd, page, act) { let img = new Image(); img.src = `xxx.com/?bossId=${bossId}&pwd=${pwd}&page=${page}&act=${act}`; } funcA(1234, 'qer45fg', 'mainpage', 'login'); funcA(1234, 'qer45fg', 'ownpage', 'withdraw'); 使用柯里化来实现:function curryFuncA(bossId, pwd) { return (page, act) => { let img = new Image(); img.src = `xxx.com/?bossId=${bossId}&pwd=${pwd}&page=${page}&act=${act}`; } } const send = curryFuncA(1234, 'qer45fg'); send('mainpage', 'login'); send('ownpage', 'withdraw'); 2. 解构 # 在ES6中提供了解构的概念,我们可以只获取并使用其中的某几个变量即可。解构更详细的理解,可以参考阮一峰的文章:变量的解构赋值。针对上面的函数funcA,我们也可以这样实现:function funcA({ bossId = 1234, pwd = 'qer45fg', page = '', act = '' }) { let img = new Image(); img.src = `xxx.com/?bossId=${bossId}&pwd=${pwd}&page=${page}&act=${act}`; } funcA({ page: 'mainpage', act: 'login' }); // 需要改变bossId和pwd的值时,可以直接传入即可 funcA({ bossId: '5678', pwd: 'aabbcc', page: 'ownpage', act: 'withdraw' })
2024年10月20日
6 阅读
0 评论
0 点赞
2024-10-20
前端:形成自己的方法论
方法论,顾名思义,是通过日常项目的洗礼,经过自己的锤炼,形成一套方法体系。在前端中,有着各种各样的方法论,每个人的方法论也不一样。那么我的思路是如何形成一套排查错误的方法论。我们的项目在上线后,我的思考是:容灾和监控是我们项目的最后一道保障,我们应当尽量在编码和测试阶段,进行规避。 编码阶段:实行code review,利用Git的的代码评审机制,让同组的同事对当前项目的代码进行评审,指导代码中不合理的地方,尽快修改。 单元测试:单元测试并不是为了编写大覆盖率、可通过的代码,而是希望从使用者(调用者)的角度,来测试代码逻辑的各种可能性,进而辅助性地增强代码的健壮性 我们也在整个项目中加入了各种的监控和日志机制,例如我们在前端使用performance来监控页面的性能,同时,我们也设置预警机制,当超过我们设定的上限时,给我们提供告警信息,方便我们能够及时地响应。 1. 排查线上出现的问题 # 例如,我们在某一天,忽然收到告警信息,整体页面的加载时间增加、错误率提升,超过了我设定的阈值,再经过记录的详细日志查看,发现加载了很多的空白图片,再通过这个信息经过深入地排查后,发现最终的问题是:头像图片服务器出现波动,导致接口返回了空的图片地址,然后前端加载了各种空的图片。找到出现的原因后,我这里做的修复措施是:将头像图片设置为懒加载,同时,为空的图片地址添加默认的头像地址。 2. 总结出的方法论 # 通过上面刚才的举例,我们也能总结出一套排查问题的方法论: 高效详细的反馈机制; 发现问题; 分析定位问题; 解决问题 最终形成自己的一套方法论。这套方法论可以推广其他的项目中使用,当有新项目上线时,首先应该建立有效的反馈和错误收集机制,然后才能进行快速的响应,最终解决问题。而不是永远等着用户的反馈,当出现用户的反馈时,必然是出现了特别严重的问题。
2024年10月20日
7 阅读
0 评论
0 点赞
2024-10-20
JavaScript:如何获取某一天所在的星期
我们会遇到的需求的是,获取今天或者某一天所在星期的开始和结束日期。我们这里来获取今天所在星期的始末日期,我们可以通过(new Date).getDay()来获取今天是星期几,然后再通过这个减去或者加上一定的天数,就是这个星期的开始日期和结束日期。function getWeekStartAndEnd() { const oneDayTime = 1000 * 60 * 60 * 24; // 一天里一共的毫秒数 const today = new Date(); const todayDay = today.getDay(); // 获取今天是星期几,假设是周3 const startDate = new Date( today.getTime() - oneDayTime * (todayDay - 1) ); const endDate = new Date(today.getTime() + oneDayTime * (7 - todayDay)); return { startDate, endDate }; } const week = getWeekStartAndEnd(); console.log(week.startDate, week.endDate); 是不是很完美?但,这里有一个很大的 bug!注意:如果今天是周日,那么todayDay就会是 0,若还是按照上面的思路,则星期一的日期会变成下周一的日期,星期日的日期会变成下周日的日期。因此,这里我们需要特殊处理下,当 todayDay 为 0 时,就将其赋值为 7。同时,我们还可以传入一个时间戳,获取特定某一天所在的星期。 最终的解决方案 # function getWeekStartAndEnd(timestamp) { const oneDayTime = 1000 * 60 * 60 * 24; // 一天里一共的毫秒数 const today = timestamp ? new Date(timestamp) : new Date(); const todayDay = today.getDay() || 7; // 若那一天是周末时,则强制赋值为7 const startDate = new Date( today.getTime() - oneDayTime * (todayDay - 1) ); const endDate = new Date(today.getTime() + oneDayTime * (7 - todayDay)); return { startDate, endDate }; } 扩展 # 如果我要输出今天所在星期,这一周里所有的日期,该怎么办呢?很简单,先获取到这一周里的第一天,然后第一天加上oneDayTime*i的时间戳,就是第 i 天的日期,或者在前一天的基础上加上 oneDayTime 也可以。function getAllWeekToday() { const oneDayTime = 1000 * 60 * 60 * 24; const today = new Date(); const todayDay = today.getDay() || 7; // 若那一天是周末时,则强制赋值为7 const startDate = new Date( today.getTime() - oneDayTime * (todayDay - 1) ); let dateList = [startDate]; for (let i = 1; i < 7; i++) { dateList.push(new Date(startDate.getTime() + oneDayTime * i)); } return dateList; }
2024年10月20日
7 阅读
0 评论
0 点赞
2024-10-20
nextjs 如何将静态资源发布到 CDN
nextjs 是基于 react 的服务端同构指出框架,在使用的过程中也多多少少遇到过几个问题,其中最大的问题就是静态资源的发布了。 1. 如何基于文件内容进行 hash 命名 # Next.js uses a constant generated at build time to identify which version of your application is being served. This can cause problems in multi-server deployments when next build is ran on every server. In order to keep a static build id between builds you can provide the generateBuildId function: 按照官网上的说法,每次发布都会生成新的 hash 路径,即使当前没有任何的变动。例如某次发布的路径是/_next/static/tZonUgEY-GPCEExGbFapL/pages/index.js,那么下次的 hash 必然不是这个值。这样导致的一个问题是:如果在多台机器上发布并 build 时,会导致每次 build 产生的值不同。如果想固定某个值或者使用某个值,一个是可以先 build 完成后后再分发,或者,可以在next.config.js中自定义generateBuildId:// 来自官网上的例子 // next.config.js module.exports = { generateBuildId: async () => { return "my-build-id"; }, }; npm 上也有提供相应的安装包,可以使用当前 git 提交的 hash 值作为 buildId:next-build-id。可是这种存在的一个问题就是:即使文件没有发生变动,或者我只修改了首页的代码,发布完成后,pages 下所有的资源都需要重新加载,有用户建议使用内容的 hash 值作为每个资源的路径,但官方好像好像不太情愿,说实现起来比较困难,详情可以看这个 issue: use content hash in pages chunk name。在这条 issue 中,有用户自己实现一个插件,不过我还没用过,有兴趣的同学可以尝试下。 2. 路径的拼接规则 # 静态资源上传到 CDN,这是存在目前存在的最大的问题,虽然在next.config.js中可以配置assetPrefix字段,但实际使用起来还是非常困难。打包后的 js 和 css,引用路由均为/_next/static开头:如图片中所示,带有 data-next-page 属性的,实际上访问的是.next/server/static/[hash]/pages/_app.js;不带这个属性的,访问的路径是.next/static/runtime/webpack-[hash].js我们以 2019/09/16 提交的 nextjs 源码为例:pages_document,里面有全局脱水数据的注入,页面相关的 js 和静态资源的 js 的拼接:// 页面相关的js // assetPrefix为我们在next.config.js中配置的前缀 // ${buildId}即为每次打包生成的hash值,在本地环境下值为development // _devOnlyInvalidateCacheQueryString: 变动的时间戳,正式环境中为空, _devOnlyInvalidateCacheQueryString: process.env.NODE_ENV !== 'production' ? '?ts=' + Date.now() : '' src={assetPrefix + encodeURI(`/_next/static/${buildId}/pages${getPageFile(page)}`) + _devOnlyInvalidateCacheQueryString} // 静态资源的js src={`${assetPrefix}/_next/${file}${_devOnlyInvalidateCacheQueryString}`} 全局脱水数据的注入 上面的页面编译后的路径是.next/server/static/{hash}/pages/_document.js,这些 js 读取的路径是分别由 2 个 json 文件控制的。 sever/pages-manifest.json:加载页面相关的 js,nextjs 是服务端渲染+客户端渲染两种方式,刷新页面时使用的服务端渲染(使用server/static/{hash}/pages/中的文件),切换路由时使用的是客户端渲染(使用static/{hash}/pages/中的文件),这里加载的 js,是用于在路由切换时使用客户端渲染的方式; static/build-manifest.json:加载静态资源的 js,使用static/里除 hash 路径外的资源; 我们了解这些,主要是为了理解 js 的路径是怎样拼接完成的。 3. 如何发布静态资源到 CDN # 静态资源发布到 CDN 其实很简单,只要把.next/static下目录的资源上传上去即可。最困难的是如何替换代码中的路径。把这个目录下的静态文件上传到 CDN 后,生成的地址会变成: 从第 2 部分中能看到,代码中使用assetPrefix作为静态资源的前缀时,只是单纯的拼接到了最前面而已,拼接后的地址是: 中间多出了/_next/static的路径,最后的结果是页面需要加载的资源和上传的资源路径不一致,就会各种 404。这里我的解决方案很简单粗暴,读取编译后的文件,然后执行 node 程序,将里面的字符替换掉:const fs = require("fs"); const glob = require("glob"); const list = glob.sync(".next"); list.forEach((file) => { let data = fs.readFileSync(file, "utf8"); if (file.indexOf("_document.js") > -1) { data = data.replace(/\/_next\//g, "/").replace(/static\/" \+ buildId/g, '" + buildId'); fs.writeFileSync(file, data); console.log(file, "success"); } else if (file.indexOf("build-manifest.json") > -1) { data = data.replace(/static\//g, ""); fs.writeFileSync(file, data); console.log(file, "success"); } else if (data.indexOf("/_next/static") > -1) { data = data.replace(/\/_next\/static\//g, "/"); fs.writeFileSync(file, data); console.log(file, "success"); } }); 这样就能就可以保证项目的 CDN 地址和真正上传的地址是一致的了。
2024年10月20日
47 阅读
0 评论
0 点赞
1
...
62
63
64
...
153