首页 文章 精选 留言 我的

精选列表

搜索[AI替代],共10000篇文章
优秀的个人博客,低调大师

🔥Star 5.1K 飞书钉钉开源替代流程引擎 FlowLong 1.1.13 发布

开源地址:https://gitee.com/aizuda/flowlong 开源地址:https://github.com/aizuda/flowlong 官网文档:https://flowlong.aizuda.com 支持全流程操作监听,仅 8 张表实现整个流程引擎(更符合中国人的思维模式设计),截至当前近 300 家企业自用登记接入使用。300 多家企业包括,国家计算中心,电信 等国企已上车,你还在等什么呢? 开源登记使用名单如下,企业版用户暂不公开 https://gitee.com/aizuda/flowlong/issues/IB5K4V Flowlong 1.1.13 主要亮点 feat: 新增支持提示可配置延迟时间 feat: 新增流程实例激活操作 opt: 优化支持连续抄送任务执行 opt: 优化执行跳转任务结束去除通知 opt: 优化流程实例挂起不允许子流程操作 opt: 优化流程作废计算耗时结束时间 opt: 优化更新任务条件 opt: 优化超时审批配置 fixed: 修复自动完成会签归档问题 fixed: 修复立即执行触发器任务异常问题 fixed: 修复抄送在并行分支后流程无法执行结束问题 fixed: 修复并行包容分支获取所有子节点不全问题 fixed: 修复连续跳过存在会签异常问题

优秀的个人博客,低调大师

🔥Star 5K 飞书钉钉开源替代流程引擎 FlowLong 1.1.12 发布

开源地址:https://gitee.com/aizuda/flowlong 开源地址:https://github.com/aizuda/flowlong 官网文档:https://flowlong.aizuda.com 支持全流程操作监听,仅 8 张表实现整个流程引擎(更符合中国人的思维模式设计),截至当前近 300 家企业自用登记接入使用。300 多家企业包括,国家计算中心,电信 等国企已上车,你还在等什么呢? 开源登记使用名单如下,企业版用户暂不公开 https://gitee.com/aizuda/flowlong/issues/IB5K4V Flowlong 1.1.12 主要亮点 feat: 新增触发器暂存功能 feat: 新增支持唤醒指定nodeKey的历史任务 opt: 优化路由节点判断逻辑 opt: 优化已阅传参 opt: 优化路由节点校验支持无条件继续执行 opt: 优化去除 PG 数据库默认 public 模式条件 fixed: 修复驳回发起人撤回限制条件错误

优秀的个人博客,低调大师

Yuzu 替代品 —— 开源 Switch 模拟器 suyu 发布首个正式版本

Yuzu 倒下后,号称是 Yuzu 转世的 "Suyu"(读作 sue-you)宣布要延续 Yuzu 并避免诉讼。 开发者 Sharpie 表示 Suyu 诞生于对 Switch 模拟的热情,以及不愿意看到 Yuzu 团队多年的工作白费。在咨询了法律专业人士(至少在法学院读了三年)后,Suyu 团队决定避免在该项目上从事任何的牟利活动。 获利能力是导致 Yuzu 被任天堂起诉的一个重要原因。因此,Suyu 声明不以任何方式支持盗版,不会提供在模拟器上运行盗版游戏的详细指南,禁止任何盗版的讨论,移除密钥,用户运行游戏将需要有合法购买的任天堂游戏。 项目主页:https://suyu.dev/ 近日,suyu 发布了首个正式版本 (v0.0.2-master)。该版本提供了大量功能改进。包括 Qlaunch 初始集成(允许用户在模拟器上使用 Switch 主系统菜单)、改进的附加组件管理器、崩溃修复、新的 UI 选项和改进、重新实现的多人 API 以及 QOL 变动等等。 此外,Suyu 还删除了所有遥测功能,而该功能先前为 Yuzu 开发人员提供了用户数据,任天堂可以利用这些数据来证明该模拟器主要用于玩盗版游戏。 更新日志: 全面重塑 生成 ICNS 图标 错误处理 Qlaunch 初始集成(存在错误 / 需要进一步测试;需要 V17.0.0 或更新版本的固件) 用于自动构建的 Gitlab ci 要求用户提供所有密钥和固件 改进的插件管理器 各种崩溃修复 支持 MacOS 的初步工作 修复 AMD 设备的视频播放问题 在 AMD 专有驱动程序上启用更多功能 重新实现多人应用程序接口 移除所有遥测功能 新的用户界面选项 / 改进 QOL 更改 下载地址:https://gitlab.com/suyu-emu/suyu/-/releases

优秀的个人博客,低调大师

一个Notepad++的替代品(Qt 6.0 恢复训练成果)

距离开始学Qt已经有几年时间了,刚开始的时候还是鹿神带着复习了C++是什么。现在虽然照样不会逆向,不过C/C++已经是常用的语言了。(碎碎念:还是想学逆向工程,可惜时间不允许) 为了毕业去干了别的方向的开发,Qt作为一个技能点虽然保留着但是很久没写了。正好前一段时间Qt 6发布了,就顺带着复习了一下Qt的使用。从12月31日到今天难得有点完整的时间。就用Notepad++作为目标准备复刻一个完整功能的Notepad++。定这个目标一是相对来说这东西比较简单,第二个是在多年前和鹿神写IDE的时候,很多功能受限于对架构的熟悉程度,不知道该怎么写。感觉是时候补完当年的遗憾了。 大概经过了从12天的开发,很多功能已经写出来了。下面是当前版本状态的一个截图 这次复刻感想还是很多的,当年对编辑器的很多幻想也都一一得到了印(po)证(jie)。曾经觉得好像很复杂的功能现在也能慢慢写出来了。代码质量虽然仍待提升,但是已经会一边写代码一边重构了。这次复习主要是想全部使用Qt的Native代码,不引入任何第三方库,也不去努力写GUI特效,想看看自己现在能在最短的时间内搞出多少功能。发现其实Qt已经解决了很多问题了,多数麻烦的功能都可以尽快的得到实现。回想一下,鬼知道当年在GUI上花了多少工夫(笑) 项目本身之后还会龟速推进下去,项目主要托管在gitee上,github上会作为镜像保留一份: https://gitee.com/Miyanaga/memo https://github.com/Harinlen/Memo 在完成一些基本的功能之前暂时没有发布计划,Mac和Linux下暂时还没做编译验证。有做Qt 5兼容的想法(也没有使用太多Qt 6的特性),但是仍需时间付出实践。看看这回能走到哪里吧。 希望2021一切顺利。

优秀的个人博客,低调大师

用 IntersectionObserver 替代滚动事件:解决页面卡顿与图片懒加载的实战方案

页面滚动时监听 `scroll` 事件做懒加载、动画触发或吸顶效果,是很多项目里的常规做法。但滚动事件触发频率极高,如果在回调里直接读取 `getBoundingClientRect()` 或修改 DOM,很容易造成掉帧,尤其在低端安卓机上滑动会明显发涩。早期常见优化是加节流,但节流时间设长了效果滞后,设短了依旧频繁计算。IntersectionObserver 提供了一种更优雅的解法:由浏览器内部监控目标元素与视口的交叉状态,只在真正进入或离开时通知回调,把计算压力从主线程移走。这篇文章会从一个实际卡顿案例出发,梳理滚动监听常见问题、IntersectionObserver 的用法与配置,并给出图片懒加载、无限滚动、元素曝光统计的落地代码,同时讨论兼容性与降级思路。 ## 滚动监听为什么会卡 先看一段典型的懒加载代码: ```js const images = document.querySelectorAll('img[data-src]'); function lazyLoad() { images.forEach(img => { const rect = img.getBoundingClientRect(); if (rect.top 0) { img.src = img.dataset.src; img.removeAttribute('data-src'); } }); } let ticking = false; window.addEventListener('scroll', () => { if (!ticking) { requestAnimationFrame(() => { lazyLoad(); ticking = false; }); ticking = true; } }); ``` 这段代码已经用 `requestAnimationFrame` 做了节流,但 `lazyLoad` 每次滚动仍会遍历所有图片,每张都触发一次强制同步布局(`getBoundingClientRect` 读取布局信息),再叠加图片解码和网络请求。页面有几百张图时,滚动过程中主线程被占满,滑动就跟不上手指。 更麻烦的是,这类代码往往在业务里散落多处:图片懒加载一个监听、曝光埋点一个监听、吸顶导航又一个监听。多个 `scroll` 回调互相竞争,谁都没法保证在 16ms 内执行完。 ## IntersectionObserver 是怎么工作的 IntersectionObserver 不监听滚动事件,而是观察元素与根元素(默认是视口)的交叉区域。当交叉比例越过设定的 `threshold` 时,浏览器触发回调。回调不在每次滚动时都执行,只在状态变化时批量触发,并且计算由浏览器内部完成,不阻塞主线程。 基本用法: ```js const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { console.log(entry.target, '进入视口'); // 停止观察,避免重复触发 observer.unobserve(entry.target); } }); }, { root: null, // 默认视口 rootMargin: '0px', // 提前或延后触发 threshold: 0 // 交叉比例达到多少时触发 }); observer.observe(document.querySelector('.target')); ``` `rootMargin` 支持类似 CSS 的写法,比如 `'200px 0px'` 表示视口上下各提前 200px 就算交叉。做懒加载时通常设置一个正向 margin,让图片在进入视口前就开始请求,用户滚到时已经加载完成,体感更顺滑。 `threshold` 可以是数字或数组。做曝光统计时常用 `[0, 0.5, 1]`,分别对应露出一点、露出一半、完全露出,方便判断有效曝光。 ## 改写图片懒加载 回到前面的场景,用 IntersectionObserver 重写: ```html ``` ```js const lazyObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (!entry.isIntersecting) return; const img = entry.target; img.src = img.dataset.src; img.removeAttribute('data-src'); // 加载完成后可以加个淡入 img.onload = () => img.classList.add('loaded'); observer.unobserve(img); }); }, { rootMargin: '200px 0px', threshold: 0 }); document.querySelectorAll('img[data-src]').forEach(img => { lazyObserver.observe(img); }); ``` 注意 HTML 里给图片写了 `width` 和 `height`,这能避免加载后布局跳动(CLS)。如果没有固定宽高,至少用 CSS 的 `aspect-ratio` 占位。 对于动态插入的图片,比如列表分页后新增节点,在插入后调用 `lazyObserver.observe(newImg)` 即可。不需要重新绑定滚动事件,逻辑收敛在一个地方。 ## 无限滚动的触发点 无限滚动常见做法是监听列表底部 sentinel 元素: ```html ... ``` ```js let loading = false; const sentinelObserver = new IntersectionObserver(async (entries) => { const entry = entries[0]; if (!entry.isIntersecting || loading) return; loading = true; await fetchNextPage(); loading = false; }, { rootMargin: '400px 0px' }); sentinelObserver.observe(document.getElementById('sentinel')); ``` 这里用 `loading` 标志防止重复请求。`rootMargin` 设为 400px,在用户距底部还有一定距离时就开始加载,减少空白等待。 和滚动监听相比,这种写法不依赖 `scrollTop` 与 `scrollHeight` 计算,也就不会因为图片加载导致页面高度变化而误判。 ## 曝光埋点的常见坑 曝光统计要求元素真正出现在视口内一定时间才算一次有效曝光。IntersectionObserver 本身只告诉交叉状态,时间需要自己控制: ```js const exposureMap = new WeakMap(); const exposureObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { const el = entry.target; if (entry.isIntersecting) { const timer = setTimeout(() => { reportExposure(el.dataset.id); observer.unobserve(el); }, 1000); exposureMap.set(el, timer); } else { const timer = exposureMap.get(el); if (timer) { clearTimeout(timer); exposureMap.delete(el); } } }); }, { threshold: 0.5 }); ``` `threshold: 0.5` 表示元素一半可见时才启动计时,1 秒后上报。如果用户快速划过,`isIntersecting` 变为 false,计时器被清除,不产生曝光。 `WeakMap` 用来存每个元素的定时器,元素被移除后自动回收,避免内存泄漏。 ## 兼容与降级 IntersectionObserver 在现代浏览器中支持良好,iOS Safari 12.2+、Chrome 51+ 都可用。如果项目仍需支持旧浏览器,有两种处理方式。 一是引入 polyfill,比如 `intersection-observer` 这个包,在入口文件顶部引入: ```js import 'intersection-observer'; ``` polyfill 内部会降级为滚动事件加节流,行为一致但性能收益消失。 二是按能力检测走两套逻辑: ```js if ('IntersectionObserver' in window) { // 用 observer } else { // 用节流滚动 } ``` 业务里更推荐第一种,统一调用方式,把降级细节交给 polyfill,避免两套代码维护成本。 ## 什么时候不适合用 IntersectionObserver 适合“元素是否出现在视口内”这类判断,但它不提供滚动位置、滚动方向、滚动速度。如果要做视差滚动、基于滚动进度的动画,还是需要 `scroll` 事件配合 `requestAnimationFrame`,或者用 CSS 的 `scroll-driven animations`。这类场景可以把 IntersectionObserver 和滚动监听结合:用 observer 判断区块是否激活,只在激活的区块内监听滚动做动画,减少不必要的计算。 另外,`root` 设为具体容器时,容器需要有明确的溢出滚动设置(`overflow: auto/scroll`),否则交叉区域计算可能不符合预期。在 iframe 或 Shadow DOM 中使用也有各自的边界情况,需要实际验证。 把懒加载、无限滚动、曝光统计从滚动事件迁移到 IntersectionObserver 后,代码量通常会减少,滚动性能的提升在图片密集的列表页尤其明显。这类改造成本不高,适合在维护老项目时顺手做掉。 推荐查看天气:http://www.362tq.com/zezhou/40tian.html 推荐查看天气:http://www.362tq.com/gaoping/ 推荐查看天气:http://www.362tq.com/gaoping/zuotian.html 推荐查看天气:http://www.362tq.com/gaoping/7tian.html 推荐查看天气:http://www.362tq.com/gaoping/10tian.html 推荐查看天气:http://www.362tq.com/gaoping/15tian.html 推荐查看天气:http://www.362tq.com/gaoping/40tian.html 推荐查看天气:http://www.362tq.com/yuncheng/ 推荐查看天气:http://www.362tq.com/yuncheng/zuotian.html 推荐查看天气:http://www.362tq.com/yuncheng/7tian.html 推荐查看天气:http://www.362tq.com/yuncheng/10tian.html 推荐查看天气:http://www.362tq.com/yuncheng/15tian.html 推荐查看天气:http://www.362tq.com/yuncheng/40tian.html 推荐查看天气:http://www.362tq.com/linyixian/ 推荐查看天气:http://www.362tq.com/linyixian/zuotian.html 推荐查看天气:http://www.362tq.com/linyixian/7tian.html 推荐查看天气:http://www.362tq.com/linyixian/10tian.html 推荐查看天气:http://www.362tq.com/linyixian/15tian.html 推荐查看天气:http://www.362tq.com/linyixian/40tian.html 推荐查看天气:http://www.362tq.com/wanrong/ 推荐查看天气:http://www.362tq.com/wanrong/zuotian.html 推荐查看天气:http://www.362tq.com/wanrong/7tian.html 推荐查看天气:http://www.362tq.com/wanrong/10tian.html 推荐查看天气:http://www.362tq.com/wanrong/15tian.html 推荐查看天气:http://www.362tq.com/wanrong/40tian.html 推荐查看天气:http://www.362tq.com/wenxi/ 推荐查看天气:http://www.362tq.com/wenxi/zuotian.html 推荐查看天气:http://www.362tq.com/wenxi/7tian.html 推荐查看天气:http://www.362tq.com/wenxi/10tian.html 推荐查看天气:http://www.362tq.com/wenxi/15tian.html 推荐查看天气:http://www.362tq.com/wenxi/40tian.html 推荐查看天气:http://www.362tq.com/jishan/ 推荐查看天气:http://www.362tq.com/jishan/zuotian.html 推荐查看天气:http://www.362tq.com/jishan/7tian.html 推荐查看天气:http://www.362tq.com/jishan/10tian.html 推荐查看天气:http://www.362tq.com/jishan/15tian.html 推荐查看天气:http://www.362tq.com/jishan/40tian.html 推荐查看天气:http://www.362tq.com/xinjiangxian/ 推荐查看天气:http://www.362tq.com/xinjiangxian/zuotian.html 推荐查看天气:http://www.362tq.com/xinjiangxian/7tian.html 推荐查看天气:http://www.362tq.com/xinjiangxian/10tian.html 推荐查看天气:http://www.362tq.com/xinjiangxian/15tian.html 推荐查看天气:http://www.362tq.com/xinjiangxian/40tian.html 推荐查看天气:http://www.362tq.com/jiangxian/ 推荐查看天气:http://www.362tq.com/jiangxian/zuotian.html 推荐查看天气:http://www.362tq.com/jiangxian/7tian.html 推荐查看天气:http://www.362tq.com/jiangxian/10tian.html 推荐查看天气:http://www.362tq.com/jiangxian/15tian.html 推荐查看天气:http://www.362tq.com/jiangxian/40tian.html 推荐查看天气:http://www.362tq.com/yuanqu/ 推荐查看天气:http://www.362tq.com/yuanqu/zuotian.html 推荐查看天气:http://www.362tq.com/yuanqu/7tian.html 推荐查看天气:http://www.362tq.com/yuanqu/10tian.html 推荐查看天气:http://www.362tq.com/yuanqu/15tian.html 推荐查看天气:http://www.362tq.com/yuanqu/40tian.html 推荐查看天气:http://www.362tq.com/xiaxian/ 推荐查看天气:http://www.362tq.com/xiaxian/zuotian.html 推荐查看天气:http://www.362tq.com/xiaxian/7tian.html 推荐查看天气:http://www.362tq.com/xiaxian/10tian.html 推荐查看天气:http://www.362tq.com/xiaxian/15tian.html 推荐查看天气:http://www.362tq.com/xiaxian/40tian.html 推荐查看天气:http://www.362tq.com/pinglu/ 推荐查看天气:http://www.362tq.com/pinglu/zuotian.html 推荐查看天气:http://www.362tq.com/pinglu/7tian.html 推荐查看天气:http://www.362tq.com/pinglu/10tian.html 推荐查看天气:http://www.362tq.com/pinglu/15tian.html 推荐查看天气:http://www.362tq.com/pinglu/40tian.html 推荐查看天气:http://www.362tq.com/ruicheng/ 推荐查看天气:http://www.362tq.com/ruicheng/zuotian.html 推荐查看天气:http://www.362tq.com/ruicheng/7tian.html 推荐查看天气:http://www.362tq.com/ruicheng/10tian.html 推荐查看天气:http://www.362tq.com/ruicheng/15tian.html 推荐查看天气:http://www.362tq.com/ruicheng/40tian.html 推荐查看天气:http://www.362tq.com/yongji/ 推荐查看天气:http://www.362tq.com/yongji/zuotian.html 推荐查看天气:http://www.362tq.com/yongji/7tian.html 推荐查看天气:http://www.362tq.com/yongji/10tian.html 推荐查看天气:http://www.362tq.com/yongji/15tian.html 推荐查看天气:http://www.362tq.com/yongji/40tian.html 推荐查看天气:http://www.362tq.com/hejin/ 推荐查看天气:http://www.362tq.com/hejin/zuotian.html 推荐查看天气:http://www.362tq.com/hejin/7tian.html 推荐查看天气:http://www.362tq.com/hejin/10tian.html 推荐查看天气:http://www.362tq.com/hejin/15tian.html 推荐查看天气:http://www.362tq.com/hejin/40tian.html 推荐查看天气:http://www.362tq.com/xuancheng/ 推荐查看天气:http://www.362tq.com/xuancheng/zuotian.html 推荐查看天气:http://www.362tq.com/xuancheng/7tian.html 推荐查看天气:http://www.362tq.com/xuancheng/10tian.html 推荐查看天气:http://www.362tq.com/xuancheng/15tian.html 推荐查看天气:http://www.362tq.com/xuancheng/40tian.html 推荐查看天气:http://www.362tq.com/langxi/ 推荐查看天气:http://www.362tq.com/langxi/zuotian.html 推荐查看天气:http://www.362tq.com/langxi/7tian.html 推荐查看天气:http://www.362tq.com/langxi/10tian.html 推荐查看天气:http://www.362tq.com/langxi/15tian.html 推荐查看天气:http://www.362tq.com/langxi/40tian.html 推荐查看天气:http://www.362tq.com/guangde/ 推荐查看天气:http://www.362tq.com/guangde/zuotian.html 推荐查看天气:http://www.362tq.com/guangde/7tian.html 推荐查看天气:http://www.362tq.com/guangde/10tian.html 推荐查看天气:http://www.362tq.com/guangde/15tian.html 推荐查看天气:http://www.362tq.com/guangde/40tian.html 推荐查看天气:http://www.362tq.com/jingxian/ 推荐查看天气:http://www.362tq.com/jingxian/zuotian.html 推荐查看天气:http://www.362tq.com/jingxian/7tian.html 推荐查看天气:http://www.362tq.com/jingxian/10tian.html 推荐查看天气:http://www.362tq.com/jingxian/15tian.html 推荐查看天气:http://www.362tq.com/jingxian/40tian.html 推荐查看天气:http://www.362tq.com/jixixian/ 推荐查看天气:http://www.362tq.com/jixixian/zuotian.html 推荐查看天气:http://www.362tq.com/jixixian/7tian.html 推荐查看天气:http://www.362tq.com/jixixian/10tian.html 推荐查看天气:http://www.362tq.com/jixixian/15tian.html 推荐查看天气:http://www.362tq.com/jixixian/40tian.html 推荐查看天气:http://www.362tq.com/jingde/ 推荐查看天气:http://www.362tq.com/jingde/zuotian.html 推荐查看天气:http://www.362tq.com/jingde/7tian.html 推荐查看天气:http://www.362tq.com/jingde/10tian.html 推荐查看天气:http://www.362tq.com/jingde/15tian.html 推荐查看天气:http://www.362tq.com/jingde/40tian.html 推荐查看天气:http://www.362tq.com/ningguo/ 推荐查看天气:http://www.362tq.com/ningguo/zuotian.html 推荐查看天气:http://www.362tq.com/ningguo/7tian.html 推荐查看天气:http://www.362tq.com/ningguo/10tian.html 推荐查看天气:http://www.362tq.com/ningguo/15tian.html 推荐查看天气:http://www.362tq.com/ningguo/40tian.html 推荐查看天气:http://www.362tq.com/liaocheng/ 推荐查看天气:http://www.362tq.com/liaocheng/zuotian.html 推荐查看天气:http://www.362tq.com/liaocheng/7tian.html 推荐查看天气:http://www.362tq.com/liaocheng/10tian.html 推荐查看天气:http://www.362tq.com/liaocheng/15tian.html 推荐查看天气:http://www.362tq.com/liaocheng/40tian.html 推荐查看天气:http://www.362tq.com/yanggu/ 推荐查看天气:http://www.362tq.com/yanggu/zuotian.html 推荐查看天气:http://www.362tq.com/yanggu/7tian.html 推荐查看天气:http://www.362tq.com/yanggu/10tian.html 推荐查看天气:http://www.362tq.com/yanggu/15tian.html 推荐查看天气:http://www.362tq.com/yanggu/40tian.html 推荐查看天气:http://www.362tq.com/xinxian/ 推荐查看天气:http://www.362tq.com/xinxian/zuotian.html 推荐查看天气:http://www.362tq.com/xinxian/7tian.html 推荐查看天气:http://www.362tq.com/xinxian/10tian.html 推荐查看天气:http://www.362tq.com/xinxian/15tian.html 推荐查看天气:http://www.362tq.com/xinxian/40tian.html 推荐查看天气:http://www.362tq.com/chiping/ 推荐查看天气:http://www.362tq.com/chiping/zuotian.html 推荐查看天气:http://www.362tq.com/chiping/7tian.html 推荐查看天气:http://www.362tq.com/chiping/10tian.html 推荐查看天气:http://www.362tq.com/chiping/15tian.html 推荐查看天气:http://www.362tq.com/chiping/40tian.html 推荐查看天气:http://www.362tq.com/donga/ 推荐查看天气:http://www.362tq.com/donga/zuotian.html 推荐查看天气:http://www.362tq.com/donga/7tian.html 推荐查看天气:http://www.362tq.com/donga/10tian.html 推荐查看天气:http://www.362tq.com/donga/15tian.html 推荐查看天气:http://www.362tq.com/donga/40tian.html 推荐查看天气:http://www.362tq.com/guanxian/ 推荐查看天气:http://www.362tq.com/guanxian/zuotian.html 推荐查看天气:http://www.362tq.com/guanxian/7tian.html 推荐查看天气:http://www.362tq.com/guanxian/10tian.html 推荐查看天气:http://www.362tq.com/guanxian/15tian.html 推荐查看天气:http://www.362tq.com/guanxian/40tian.html 推荐查看天气:http://www.362tq.com/gaotang/ 推荐查看天气:http://www.362tq.com/gaotang/zuotian.html 推荐查看天气:http://www.362tq.com/gaotang/7tian.html 推荐查看天气:http://www.362tq.com/gaotang/10tian.html 推荐查看天气:http://www.362tq.com/gaotang/15tian.html 推荐查看天气:http://www.362tq.com/gaotang/40tian.html 推荐查看天气:http://www.362tq.com/linqing/ 推荐查看天气:http://www.362tq.com/linqing/zuotian.html 推荐查看天气:http://www.362tq.com/linqing/7tian.html 推荐查看天气:http://www.362tq.com/linqing/10tian.html 推荐查看天气:http://www.362tq.com/linqing/15tian.html 推荐查看天气:http://www.362tq.com/linqing/40tian.html 推荐查看天气:http://www.362tq.com/dongqu/ 推荐查看天气:http://www.362tq.com/dongqu/zuotian.html 推荐查看天气:http://www.362tq.com/dongqu/7tian.html 推荐查看天气:http://www.362tq.com/dongqu/10tian.html 推荐查看天气:http://www.362tq.com/dongqu/15tian.html 推荐查看天气:http://www.362tq.com/dongqu/40tian.html 推荐查看天气:http://www.362tq.com/jiulongcheng/ 推荐查看天气:http://www.362tq.com/jiulongcheng/zuotian.html 推荐查看天气:http://www.362tq.com/jiulongcheng/7tian.html 推荐查看天气:http://www.362tq.com/jiulongcheng/10tian.html 推荐查看天气:http://www.362tq.com/jiulongcheng/15tian.html 推荐查看天气:http://www.362tq.com/jiulongcheng/40tian.html 推荐查看天气:http://www.362tq.com/taiwan/ 推荐查看天气:http://www.362tq.com/taiwan/zuotian.html 推荐查看天气:http://www.362tq.com/taiwan/7tian.html 推荐查看天气:http://www.362tq.com/taiwan/10tian.html 推荐查看天气:http://www.362tq.com/taiwan/15tian.html 推荐查看天气:http://www.362tq.com/taiwan/40tian.html 推荐查看天气:http://www.362tq.com/taibei/ 推荐查看天气:http://www.362tq.com/taibei/zuotian.html 推荐查看天气:http://www.362tq.com/taibei/7tian.html 推荐查看天气:http://www.362tq.com/taibei/10tian.html 推荐查看天气:http://www.362tq.com/taibei/15tian.html 推荐查看天气:http://www.362tq.com/taibei/40tian.html 推荐查看天气:http://www.362tq.com/jilong/

优秀的个人博客,低调大师

JavaScript 中 requestAnimationFrame 在后台标签页不触发的问题排查与替代方案

做数据大屏或者定时轮询渲染的时候,很容易遇到一个现象:页面切到后台再切回来,某些依赖于 requestAnimationFrame 的动画或状态更新会「卡住」几秒,甚至像是什么都没发生。浏览器为了省电和降低 CPU,在标签页不可见时会暂停 requestAnimationFrame 的回调,把它降频甚至完全冻结。但业务里可能用它来驱动非纯视觉任务,比如轮询状态、计算布局、播放帧序列,这时候就出问题了。下面从一次实际排查过程说起,看看为什么会这样,以及除了切回页面强制刷新外,还有哪些更可控的写法。 ## 问题复现 假设有一个组件用 rAF 来做一个平滑的数字滚动,同时每帧检查一下远程任务是否完成。 ```js function startLoop() { let last = performance.now(); function frame(now) { const delta = now - last; if (delta > 16) { renderNumber(); checkTaskStatus(); last = now; } requestAnimationFrame(frame); } requestAnimationFrame(frame); } ``` 在浏览器里正常切换标签页后,`checkTaskStatus` 不会执行,等回来时又恢复正常。如果任务完成依赖这个轮询,用户切走再回来可能发现状态还停在旧数据上。 ## 为什么后台标签页没回调 规范里没有规定 rAF 在页面不可见时应该继续以 60fps 运行。实际情况是,大多数浏览器在文档进入 hidden 状态后,会把 rAF 回调挂起,或者降低到非常低的频率(比如 1fps 甚至 0)。因为 rAF 的本意是配合屏幕刷新,不可见的页面没有刷新需求,继续运行等于白白耗电。 可以用 `document.visibilityState` 验证: ```js let count = 0; function tick() { count++; console.log('frame', count, document.visibilityState); requestAnimationFrame(tick); } requestAnimationFrame(tick); ``` 在后台标签页停几秒再切回来,控制台里帧数几乎不增长。这不是 bug,是节能策略。 ## 如果只是做动画,应该怎么做 纯视觉动画在页面不可见时暂停是合理的,用户看不到,继续跑也没意义。如果希望切回来时从当前状态继续,而不是「时间跳变」,可以用时间戳计算差值,而不是依赖帧数累加。 ```js let startTime = null; function animate(now) { if (startTime === null) startTime = now; const elapsed = now - startTime; const progress = Math.min(elapsed / 1000, 1); element.style.transform = `translateX(${progress * 200}px)`; if (progress { checkTaskStatus(); }, 1000); } function stopPolling() { if (timer) clearInterval(timer); timer = null; } ``` 如果任务对时效性要求更高,可以在 `visibilitychange` 里做补偿:切回页面时立即执行一次。 ```js document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { checkTaskStatus(); } }); ``` ## 后台仍然需要执行的场景 有些逻辑必须持续运行,比如 WebSocket 心跳、音频处理、Web Worker 里的计算。这些不应该依赖主线程的 rAF。常见做法是把逻辑放进 Worker,Worker 的定时器不会被页面可见性冻结(但可能被浏览器整体节流策略影响,至少不受 visibility 直接控制)。 ```js // worker.js setInterval(() => { self.postMessage('heartbeat'); }, 5000); // main.js const worker = new Worker('worker.js'); worker.onmessage = (e) => { if (e.data === 'heartbeat') { sendHeartbeat(); } }; ``` WebSocket 心跳也可以直接用 `setInterval` 在页面里发,切后台时浏览器可能降低频率,但多数情况下不会完全停止。真正完全停止的情况出现在移动端切到桌面或锁屏,这时只能靠 Service Worker 或原生推送补足。 ## 兼容旧代码的折中处理 如果项目里已经大量使用了 rAF 做非视觉逻辑,全部重写成本高。可以在封装层加一个开关,在页面隐藏时改用 `setInterval` 兜底,可见时再切回 rAF。 ```js class FrameLoop { constructor(callback, fallbackInterval = 1000) { this.callback = callback; this.fallbackInterval = fallbackInterval; this.rafId = null; this.timer = null; this.onVisibilityChange = this.onVisibilityChange.bind(this); document.addEventListener('visibilitychange', this.onVisibilityChange); this.start(); } start() { this.stop(); if (document.visibilityState === 'visible') { const loop = () => { this.callback(); this.rafId = requestAnimationFrame(loop); }; this.rafId = requestAnimationFrame(loop); } else { this.timer = setInterval(() => this.callback(), this.fallbackInterval); } } stop() { if (this.rafId) cancelAnimationFrame(this.rafId); if (this.timer) clearInterval(this.timer); this.rafId = null; this.timer = null; } onVisibilityChange() { this.start(); } destroy() { this.stop(); document.removeEventListener('visibilitychange', this.onVisibilityChange); } } ``` 这样既保留了可见时的帧同步,又保证后台不会完全停止响应。回调里要注意不要做太重的事情,因为兜底间隔可能只有 1 秒,堆积起来反而更卡。 理解 rAF 的节能行为之后,选型就清晰了:画面相关用它,定时任务用定时器,必须后台运行的放 Worker。切页面的卡顿大多不是代码写错,而是把两种不同目的的东西混在了一起。 推荐查看天气:http://www.362tq.com/wangcang/zuotian.html 推荐查看天气:http://www.362tq.com/wangcang/7tian.html 推荐查看天气:http://www.362tq.com/wangcang/10tian.html 推荐查看天气:http://www.362tq.com/wangcang/15tian.html 推荐查看天气:http://www.362tq.com/wangcang/40tian.html 推荐查看天气:http://www.362tq.com/qingchuan/ 推荐查看天气:http://www.362tq.com/qingchuan/zuotian.html 推荐查看天气:http://www.362tq.com/qingchuan/7tian.html 推荐查看天气:http://www.362tq.com/qingchuan/10tian.html 推荐查看天气:http://www.362tq.com/qingchuan/15tian.html 推荐查看天气:http://www.362tq.com/qingchuan/40tian.html 推荐查看天气:http://www.362tq.com/jiange/ 推荐查看天气:http://www.362tq.com/jiange/zuotian.html 推荐查看天气:http://www.362tq.com/jiange/7tian.html 推荐查看天气:http://www.362tq.com/jiange/10tian.html 推荐查看天气:http://www.362tq.com/jiange/15tian.html 推荐查看天气:http://www.362tq.com/jiange/40tian.html 推荐查看天气:http://www.362tq.com/cangxi/ 推荐查看天气:http://www.362tq.com/cangxi/zuotian.html 推荐查看天气:http://www.362tq.com/cangxi/7tian.html 推荐查看天气:http://www.362tq.com/cangxi/10tian.html 推荐查看天气:http://www.362tq.com/cangxi/15tian.html 推荐查看天气:http://www.362tq.com/cangxi/40tian.html 推荐查看天气:http://www.362tq.com/suining/ 推荐查看天气:http://www.362tq.com/suining/zuotian.html 推荐查看天气:http://www.362tq.com/suining/7tian.html 推荐查看天气:http://www.362tq.com/suining/10tian.html 推荐查看天气:http://www.362tq.com/suining/15tian.html 推荐查看天气:http://www.362tq.com/suining/40tian.html 推荐查看天气:http://www.362tq.com/chuanshan/ 推荐查看天气:http://www.362tq.com/chuanshan/zuotian.html 推荐查看天气:http://www.362tq.com/chuanshan/7tian.html 推荐查看天气:http://www.362tq.com/chuanshan/10tian.html 推荐查看天气:http://www.362tq.com/chuanshan/15tian.html 推荐查看天气:http://www.362tq.com/chuanshan/40tian.html 推荐查看天气:http://www.362tq.com/anju/ 推荐查看天气:http://www.362tq.com/anju/zuotian.html 推荐查看天气:http://www.362tq.com/anju/7tian.html 推荐查看天气:http://www.362tq.com/anju/10tian.html 推荐查看天气:http://www.362tq.com/anju/15tian.html 推荐查看天气:http://www.362tq.com/anju/40tian.html 推荐查看天气:http://www.362tq.com/pengxi/ 推荐查看天气:http://www.362tq.com/pengxi/zuotian.html 推荐查看天气:http://www.362tq.com/pengxi/7tian.html 推荐查看天气:http://www.362tq.com/pengxi/10tian.html 推荐查看天气:http://www.362tq.com/pengxi/15tian.html 推荐查看天气:http://www.362tq.com/pengxi/40tian.html 推荐查看天气:http://www.362tq.com/shehong/ 推荐查看天气:http://www.362tq.com/shehong/zuotian.html 推荐查看天气:http://www.362tq.com/shehong/7tian.html 推荐查看天气:http://www.362tq.com/shehong/10tian.html 推荐查看天气:http://www.362tq.com/shehong/15tian.html 推荐查看天气:http://www.362tq.com/shehong/40tian.html 推荐查看天气:http://www.362tq.com/daying/ 推荐查看天气:http://www.362tq.com/daying/zuotian.html 推荐查看天气:http://www.362tq.com/daying/7tian.html 推荐查看天气:http://www.362tq.com/daying/10tian.html 推荐查看天气:http://www.362tq.com/daying/15tian.html 推荐查看天气:http://www.362tq.com/daying/40tian.html 推荐查看天气:http://www.362tq.com/neijiang/ 推荐查看天气:http://www.362tq.com/neijiang/zuotian.html 推荐查看天气:http://www.362tq.com/neijiang/7tian.html 推荐查看天气:http://www.362tq.com/neijiang/10tian.html 推荐查看天气:http://www.362tq.com/neijiang/15tian.html 推荐查看天气:http://www.362tq.com/neijiang/40tian.html 推荐查看天气:http://www.362tq.com/dongxing/ 推荐查看天气:http://www.362tq.com/dongxing/zuotian.html 推荐查看天气:http://www.362tq.com/dongxing/7tian.html 推荐查看天气:http://www.362tq.com/dongxing/10tian.html 推荐查看天气:http://www.362tq.com/dongxing/15tian.html 推荐查看天气:http://www.362tq.com/dongxing/40tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/ 推荐查看天气:http://www.362tq.com/najiangweiyuan/zuotian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/7tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/10tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/15tian.html 推荐查看天气:http://www.362tq.com/najiangweiyuan/40tian.html 推荐查看天气:http://www.362tq.com/zizhong/ 推荐查看天气:http://www.362tq.com/zizhong/zuotian.html 推荐查看天气:http://www.362tq.com/zizhong/7tian.html 推荐查看天气:http://www.362tq.com/zizhong/10tian.html 推荐查看天气:http://www.362tq.com/zizhong/15tian.html 推荐查看天气:http://www.362tq.com/zizhong/40tian.html 推荐查看天气:http://www.362tq.com/longchang/ 推荐查看天气:http://www.362tq.com/longchang/zuotian.html 推荐查看天气:http://www.362tq.com/longchang/7tian.html 推荐查看天气:http://www.362tq.com/longchang/10tian.html 推荐查看天气:http://www.362tq.com/longchang/15tian.html 推荐查看天气:http://www.362tq.com/longchang/40tian.html 推荐查看天气:http://www.362tq.com/leshan/ 推荐查看天气:http://www.362tq.com/leshan/zuotian.html 推荐查看天气:http://www.362tq.com/leshan/7tian.html 推荐查看天气:http://www.362tq.com/leshan/10tian.html 推荐查看天气:http://www.362tq.com/leshan/15tian.html 推荐查看天气:http://www.362tq.com/leshan/40tian.html 推荐查看天气:http://www.362tq.com/shizhong/ 推荐查看天气:http://www.362tq.com/shizhong/zuotian.html 推荐查看天气:http://www.362tq.com/shizhong/7tian.html 推荐查看天气:http://www.362tq.com/shizhong/10tian.html 推荐查看天气:http://www.362tq.com/shizhong/15tian.html 推荐查看天气:http://www.362tq.com/shizhong/40tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/ 推荐查看天气:http://www.362tq.com/wutongqiao/zuotian.html 推荐查看天气:http://www.362tq.com/wutongqiao/7tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/10tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/15tian.html 推荐查看天气:http://www.362tq.com/wutongqiao/40tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/ 推荐查看天气:http://www.362tq.com/jinkouhe/zuotian.html 推荐查看天气:http://www.362tq.com/jinkouhe/7tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/10tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/15tian.html 推荐查看天气:http://www.362tq.com/jinkouhe/40tian.html 推荐查看天气:http://www.362tq.com/jianwei/ 推荐查看天气:http://www.362tq.com/jianwei/zuotian.html 推荐查看天气:http://www.362tq.com/jianwei/7tian.html 推荐查看天气:http://www.362tq.com/jianwei/10tian.html 推荐查看天气:http://www.362tq.com/jianwei/15tian.html 推荐查看天气:http://www.362tq.com/jianwei/40tian.html 推荐查看天气:http://www.362tq.com/jingyan/ 推荐查看天气:http://www.362tq.com/jingyan/zuotian.html 推荐查看天气:http://www.362tq.com/jingyan/7tian.html 推荐查看天气:http://www.362tq.com/jingyan/10tian.html 推荐查看天气:http://www.362tq.com/jingyan/15tian.html 推荐查看天气:http://www.362tq.com/jingyan/40tian.html 推荐查看天气:http://www.362tq.com/jiajiang/ 推荐查看天气:http://www.362tq.com/jiajiang/zuotian.html 推荐查看天气:http://www.362tq.com/jiajiang/7tian.html 推荐查看天气:http://www.362tq.com/jiajiang/10tian.html 推荐查看天气:http://www.362tq.com/jiajiang/15tian.html 推荐查看天气:http://www.362tq.com/jiajiang/40tian.html 推荐查看天气:http://www.362tq.com/muchuan/ 推荐查看天气:http://www.362tq.com/muchuan/zuotian.html 推荐查看天气:http://www.362tq.com/muchuan/7tian.html 推荐查看天气:http://www.362tq.com/muchuan/10tian.html 推荐查看天气:http://www.362tq.com/muchuan/15tian.html 推荐查看天气:http://www.362tq.com/muchuan/40tian.html 推荐查看天气:http://www.362tq.com/ebian/ 推荐查看天气:http://www.362tq.com/ebian/zuotian.html 推荐查看天气:http://www.362tq.com/ebian/7tian.html 推荐查看天气:http://www.362tq.com/ebian/10tian.html 推荐查看天气:http://www.362tq.com/ebian/15tian.html 推荐查看天气:http://www.362tq.com/ebian/40tian.html 推荐查看天气:http://www.362tq.com/mabian/ 推荐查看天气:http://www.362tq.com/mabian/zuotian.html 推荐查看天气:http://www.362tq.com/mabian/7tian.html 推荐查看天气:http://www.362tq.com/mabian/10tian.html 推荐查看天气:http://www.362tq.com/mabian/15tian.html 推荐查看天气:http://www.362tq.com/mabian/40tian.html 推荐查看天气:http://www.362tq.com/emeishan/ 推荐查看天气:http://www.362tq.com/emeishan/zuotian.html 推荐查看天气:http://www.362tq.com/emeishan/7tian.html 推荐查看天气:http://www.362tq.com/emeishan/10tian.html 推荐查看天气:http://www.362tq.com/emeishan/15tian.html 推荐查看天气:http://www.362tq.com/emeishan/40tian.html 推荐查看天气:http://www.362tq.com/nanchong/ 推荐查看天气:http://www.362tq.com/nanchong/zuotian.html 推荐查看天气:http://www.362tq.com/nanchong/7tian.html 推荐查看天气:http://www.362tq.com/nanchong/10tian.html 推荐查看天气:http://www.362tq.com/nanchong/15tian.html 推荐查看天气:http://www.362tq.com/nanchong/40tian.html 推荐查看天气:http://www.362tq.com/shunqing/ 推荐查看天气:http://www.362tq.com/shunqing/zuotian.html 推荐查看天气:http://www.362tq.com/shunqing/7tian.html 推荐查看天气:http://www.362tq.com/shunqing/10tian.html 推荐查看天气:http://www.362tq.com/shunqing/15tian.html 推荐查看天气:http://www.362tq.com/shunqing/40tian.html 推荐查看天气:http://www.362tq.com/jialing/ 推荐查看天气:http://www.362tq.com/jialing/zuotian.html 推荐查看天气:http://www.362tq.com/jialing/7tian.html 推荐查看天气:http://www.362tq.com/jialing/10tian.html 推荐查看天气:http://www.362tq.com/jialing/15tian.html 推荐查看天气:http://www.362tq.com/jialing/40tian.html 推荐查看天气:http://www.362tq.com/nanbu/ 推荐查看天气:http://www.362tq.com/nanbu/zuotian.html 推荐查看天气:http://www.362tq.com/nanbu/7tian.html 推荐查看天气:http://www.362tq.com/nanbu/10tian.html 推荐查看天气:http://www.362tq.com/nanbu/15tian.html 推荐查看天气:http://www.362tq.com/nanbu/40tian.html 推荐查看天气:http://www.362tq.com/yingshan/ 推荐查看天气:http://www.362tq.com/yingshan/zuotian.html 推荐查看天气:http://www.362tq.com/yingshan/7tian.html 推荐查看天气:http://www.362tq.com/yingshan/10tian.html 推荐查看天气:http://www.362tq.com/yingshan/15tian.html 推荐查看天气:http://www.362tq.com/yingshan/40tian.html 推荐查看天气:http://www.362tq.com/pengan/ 推荐查看天气:http://www.362tq.com/pengan/zuotian.html 推荐查看天气:http://www.362tq.com/pengan/7tian.html 推荐查看天气:http://www.362tq.com/pengan/10tian.html 推荐查看天气:http://www.362tq.com/pengan/15tian.html 推荐查看天气:http://www.362tq.com/pengan/40tian.html 推荐查看天气:http://www.362tq.com/yilong/ 推荐查看天气:http://www.362tq.com/yilong/zuotian.html 推荐查看天气:http://www.362tq.com/yilong/7tian.html 推荐查看天气:http://www.362tq.com/yilong/10tian.html 推荐查看天气:http://www.362tq.com/yilong/15tian.html 推荐查看天气:http://www.362tq.com/yilong/40tian.html 推荐查看天气:http://www.362tq.com/xichong/ 推荐查看天气:http://www.362tq.com/xichong/zuotian.html 推荐查看天气:http://www.362tq.com/xichong/7tian.html

优秀的个人博客,低调大师

Vue 3 中 reactive 对象解构丢失响应性的真实原因与替代写法

在 Vue 3 项目里,不少人在组合式 API 中写 `const { count } = reactive({ count: 0 })` 之后,发现模板里 `count` 永远不会更新。这个问题通常不是 Vue 的 bug,而是 reactive 返回的是 Proxy 对象,解构本质上就是读取属性值再赋给新变量;如果属性是原始类型,新变量拿到的是一个普通值,和原来的 Proxy 已经断开联系。模板或 computed 再访问这个普通变量时,Vue 的依赖收集不会建立到原对象上,因此更新源对象也不会触发视图。常见场景包括把 reactive 表单字段解构给子组件、从 store 中解构状态、在组合式函数返回对象后直接解构使用。这篇文章会从 Proxy 的读取机制讲起,结合真实代码说明为什么解构后失效,并给出 toRefs、toRef、computed 以及直接保留对象引用的写法,同时对比 ref 和 reactive 在解构行为上的差异。 ## 问题复现 先看一段很常见的代码: ```vue {{ count }} ``` 点击按钮后,`state.count` 确实变了,但页面上的 `count` 不动。如果打开 Vue Devtools 观察,会发现组件并没有因为 `count` 变化而重新渲染。原因是 `const { count } = state` 执行时,`state.count` 被读取了一次,返回的是数字 `0`。这个 `0` 被复制到新变量 `count` 里,之后 `state.count++` 修改的是 Proxy 上的属性,和那个数字变量没有任何引用关系。 ## Proxy 的读取和依赖收集 Vue 3 的 `reactive` 基于 Proxy 实现。访问 `state.count` 时,会走到 handler 的 `get` 陷阱,Vue 在这里做两件事:返回当前值,同时把当前正在运行的 effect(比如组件的渲染 effect 或 computed effect)记录到 `count` 这个 key 的依赖集合里。 ```js const state = reactive({ count: 0 }) // 这一行发生在组件渲染函数里时,会收集依赖 template: () => h('div', state.count) ``` 解构发生在组件 setup 阶段,那时候渲染 effect 还没开始运行。更关键的是,解构之后模板里用的是局部变量 `count`,它已经不再是 Proxy 的属性访问,所以后续 `state.count++` 触发的是 Proxy 的 `set`,通知的是之前收集到的依赖,而模板根本没有订阅过这个局部变量。 ## toRefs 为什么能解决 `toRefs` 做的事是把 reactive 对象的每个属性转成 ref,并且这个 ref 的 `value` 访问会转发到原对象上: ```js import { reactive, toRefs } from 'vue' const state = reactive({ count: 0, name: 'vue' }) const { count, name } = toRefs(state) count.value++ // 等价于 state.count++ ``` 在模板里,Vue 会自动解包 ref,所以可以继续写 `{{ count }}`。这时候 `count` 是一个 ref 对象,模板访问 `count.value` 时会经过 ref 的 getter,而 ref 的 getter 内部再去读 `state.count`,依赖收集依然落在原来的 reactive 对象上。 toRefs 返回的是普通对象,不是 Proxy,但每个属性都是 ref。对原始类型属性来说,这是解构后保持响应性的标准做法。 ## toRef 只取单个属性 如果只关心一个字段,不需要把整个对象都转掉: ```js import { reactive, toRef } from 'vue' const state = reactive({ count: 0, name: 'vue' }) const count = toRef(state, 'count') count.value++ ``` `toRef` 和 `toRefs` 内部机制类似,都是创建一个与源对象属性双向联动的 ref。区别在于 `toRef` 针对单个 key,适合从 props 或 store 中提取某个字段。 ## 解构 props 的响应性 `defineProps` 返回的对象本身是响应式的,但直接解构同样会失去响应性: ```vue ``` Vue 3.5 之前,官方推荐用 `toRef` 或 `toRefs`: ```js import { toRef } from 'vue' const props = defineProps({ title: String }) const title = toRef(props, 'title') ``` Vue 3.5 开始,`defineProps` 返回的对象在解构时会保留响应性,编译器会识别解构并生成对应的 getter。如果项目锁在 3.4 或更早版本,还是需要手动 `toRef`。 ## reactive 嵌套对象解构的坑 嵌套对象解构后丢失响应性更隐蔽: ```js const state = reactive({ user: { name: 'a' } }) const { user } = state user.name = 'b' // 这个操作本身是响应式的,因为 user 还是 Proxy 对象 ``` 这里 `user` 仍然是 Proxy,所以修改 `user.name` 会触发更新。但如果再往下解构: ```js const { name } = state.user name = 'b' // 无效,name 是原始字符串 ``` 嵌套解构到原始类型那一层,响应性就断了。实际项目里常见于从表单对象中取出某个字段传给子组件,子组件内部再修改时发现父组件不更新。 ## ref 解构的差异 `ref` 本身是一个对象,解构它的 `.value` 也会丢失响应性: ```js const count = ref(0) const { value } = count value++ // 无效 ``` 但模板中 ref 会自动解包,所以直接写 `{{ count }}` 没问题。如果要把 ref 传给组合式函数再解构,必须保留 ref 本身,或者用 `toRef` 重新包一层。 ```js function useCounter() { const count = ref(0) return { count } } const { count } = useCounter() // 这里 count 还是 ref,没问题 ``` 组合式函数返回对象时,如果返回的是 reactive 对象,调用方解构就会出问题。所以很多库选择返回 ref 集合,而不是 reactive 对象。 ## 什么时候可以直接解构 如果解构出来的值只用于一次性计算,不参与后续更新,直接解构没问题: ```js const state = reactive({ list: [1, 2, 3] }) const { list } = state const total = list.reduce((a, b) => a + b, 0) ``` 只要 `list` 后续不会变化,或者变化后不需要重新计算,就不涉及响应性丢失。真正的坑在于把解构结果放进模板、computed 或 watch 里,期待它跟随源对象变化。 ## 在 store 中的实际写法 Pinia 的 store 返回的是 reactive 对象,直接解构 state 会失去响应性: ```js const store = useUserStore() const { name } = store // 失去响应性 ``` Pinia 提供了 `storeToRefs` 来处理: ```js import { storeToRefs } from 'pinia' const store = useUserStore() const { name } = storeToRefs(store) ``` `storeToRefs` 会跳过 actions,只为 state 和 getters 创建 ref。这样解构后模板里直接用 `{{ name }}`,修改用 `store.name = 'x'`,两边保持同步。 ## 一个容易忽略的 computed 场景 有人会写: ```js const state = reactive({ count: 0 }) const { count } = state const double = computed(() => count * 2) ``` `double` 不会随 `state.count` 更新,因为 computed 内部只读了普通变量 `count`,没有访问任何响应式属性。改成 `toRef` 后: ```js const count = toRef(state, 'count') const double = computed(() => count.value * 2) ``` computed 在第一次求值时读到 `count.value`,进入 ref 的 getter,再读到 `state.count`,依赖就被正确收集了。 ## 组合式函数返回值的取舍 写组合式函数时,返回 reactive 对象让调用方直接解构,通常是不友好的。更稳妥的做法是返回 ref: ```js export function useForm() { const form = reactive({ username: '', password: '' }) function reset() { form.username = '' form.password = '' } return { form, reset } } ``` 调用方要么保留 `form` 整体使用,要么用 `toRefs(form)` 解构。如果组合式函数明确只暴露几个字段,可以内部就转好: ```js export function useForm() { const form = reactive({ username: '', password: '' }) const { username, password } = toRefs(form) return { username, password, form } } ``` 这样调用方解构 `username` 时拿到的已经是 ref,不会踩坑。 ## 小结一下这个行为的记忆点 reactive 的解构丢失响应性不是设计缺陷,而是 JavaScript 值传递和 Proxy 依赖收集共同作用的结果。解构原始类型属性等于复制值,复制之后和源对象无关;解构嵌套对象属性时,如果该属性本身是 Proxy,那它还保持响应性,继续往下解构原始类型才会断。需要解构时,优先考虑 `toRefs`、`toRef`、`storeToRefs` 或直接访问原对象属性。模板里写 `state.count` 永远是最直接、最不容易出错的方式。 推荐查看天气:https://www.0dtq.com/jianning/ 推荐查看天气:https://www.0dtq.com/jianning/zuotian.html 推荐查看天气:https://www.0dtq.com/jianning/7tian.html 推荐查看天气:https://www.0dtq.com/jianning/10tian.html 推荐查看天气:https://www.0dtq.com/jianning/15tian.html 推荐查看天气:https://www.0dtq.com/jianning/40tian.html 推荐查看天气:https://www.0dtq.com/yongan/ 推荐查看天气:https://www.0dtq.com/yongan/zuotian.html 推荐查看天气:https://www.0dtq.com/yongan/7tian.html 推荐查看天气:https://www.0dtq.com/yongan/10tian.html 推荐查看天气:https://www.0dtq.com/yongan/15tian.html 推荐查看天气:https://www.0dtq.com/yongan/40tian.html 推荐查看天气:https://www.0dtq.com/quanzhou/ 推荐查看天气:https://www.0dtq.com/quanzhou/zuotian.html 推荐查看天气:https://www.0dtq.com/quanzhou/7tian.html 推荐查看天气:https://www.0dtq.com/quanzhou/10tian.html 推荐查看天气:https://www.0dtq.com/quanzhou/15tian.html 推荐查看天气:https://www.0dtq.com/quanzhou/40tian.html 推荐查看天气:https://www.0dtq.com/fengze/ 推荐查看天气:https://www.0dtq.com/fengze/zuotian.html 推荐查看天气:https://www.0dtq.com/fengze/7tian.html 推荐查看天气:https://www.0dtq.com/fengze/10tian.html 推荐查看天气:https://www.0dtq.com/fengze/15tian.html 推荐查看天气:https://www.0dtq.com/fengze/40tian.html 推荐查看天气:https://www.0dtq.com/quangang/ 推荐查看天气:https://www.0dtq.com/quangang/zuotian.html 推荐查看天气:https://www.0dtq.com/quangang/7tian.html 推荐查看天气:https://www.0dtq.com/quangang/10tian.html 推荐查看天气:https://www.0dtq.com/quangang/15tian.html 推荐查看天气:https://www.0dtq.com/quangang/40tian.html 推荐查看天气:https://www.0dtq.com/huian/ 推荐查看天气:https://www.0dtq.com/huian/zuotian.html 推荐查看天气:https://www.0dtq.com/huian/7tian.html 推荐查看天气:https://www.0dtq.com/huian/10tian.html 推荐查看天气:https://www.0dtq.com/huian/15tian.html 推荐查看天气:https://www.0dtq.com/huian/40tian.html 推荐查看天气:https://www.0dtq.com/anxixian/ 推荐查看天气:https://www.0dtq.com/anxixian/zuotian.html 推荐查看天气:https://www.0dtq.com/anxixian/7tian.html 推荐查看天气:https://www.0dtq.com/anxixian/10tian.html 推荐查看天气:https://www.0dtq.com/anxixian/15tian.html 推荐查看天气:https://www.0dtq.com/anxixian/40tian.html 推荐查看天气:https://www.0dtq.com/yongchun/ 推荐查看天气:https://www.0dtq.com/yongchun/zuotian.html 推荐查看天气:https://www.0dtq.com/yongchun/7tian.html 推荐查看天气:https://www.0dtq.com/yongchun/10tian.html 推荐查看天气:https://www.0dtq.com/yongchun/15tian.html 推荐查看天气:https://www.0dtq.com/yongchun/40tian.html 推荐查看天气:https://www.0dtq.com/dehua/ 推荐查看天气:https://www.0dtq.com/dehua/zuotian.html 推荐查看天气:https://www.0dtq.com/dehua/7tian.html 推荐查看天气:https://www.0dtq.com/dehua/10tian.html 推荐查看天气:https://www.0dtq.com/dehua/15tian.html 推荐查看天气:https://www.0dtq.com/dehua/40tian.html 推荐查看天气:https://www.0dtq.com/shishi/ 推荐查看天气:https://www.0dtq.com/shishi/zuotian.html 推荐查看天气:https://www.0dtq.com/shishi/7tian.html 推荐查看天气:https://www.0dtq.com/shishi/10tian.html 推荐查看天气:https://www.0dtq.com/shishi/15tian.html 推荐查看天气:https://www.0dtq.com/shishi/40tian.html 推荐查看天气:https://www.0dtq.com/jinjiang/ 推荐查看天气:https://www.0dtq.com/jinjiang/zuotian.html 推荐查看天气:https://www.0dtq.com/jinjiang/7tian.html 推荐查看天气:https://www.0dtq.com/jinjiang/10tian.html 推荐查看天气:https://www.0dtq.com/jinjiang/15tian.html 推荐查看天气:https://www.0dtq.com/jinjiang/40tian.html 推荐查看天气:https://www.0dtq.com/quanzhounanan/ 推荐查看天气:https://www.0dtq.com/quanzhounanan/zuotian.html 推荐查看天气:https://www.0dtq.com/quanzhounanan/7tian.html 推荐查看天气:https://www.0dtq.com/quanzhounanan/10tian.html 推荐查看天气:https://www.0dtq.com/quanzhounanan/15tian.html 推荐查看天气:https://www.0dtq.com/quanzhounanan/40tian.html 推荐查看天气:https://www.0dtq.com/zhangzhou/ 推荐查看天气:https://www.0dtq.com/zhangzhou/zuotian.html 推荐查看天气:https://www.0dtq.com/zhangzhou/7tian.html 推荐查看天气:https://www.0dtq.com/zhangzhou/10tian.html 推荐查看天气:https://www.0dtq.com/zhangzhou/15tian.html 推荐查看天气:https://www.0dtq.com/zhangzhou/40tian.html 推荐查看天气:https://www.0dtq.com/yunxiao/ 推荐查看天气:https://www.0dtq.com/yunxiao/zuotian.html 推荐查看天气:https://www.0dtq.com/yunxiao/7tian.html 推荐查看天气:https://www.0dtq.com/yunxiao/10tian.html 推荐查看天气:https://www.0dtq.com/yunxiao/15tian.html 推荐查看天气:https://www.0dtq.com/yunxiao/40tian.html 推荐查看天气:https://www.0dtq.com/zhangpu/ 推荐查看天气:https://www.0dtq.com/zhangpu/zuotian.html 推荐查看天气:https://www.0dtq.com/zhangpu/7tian.html 推荐查看天气:https://www.0dtq.com/zhangpu/10tian.html 推荐查看天气:https://www.0dtq.com/zhangpu/15tian.html 推荐查看天气:https://www.0dtq.com/zhangpu/40tian.html 推荐查看天气:https://www.0dtq.com/zhaoan/ 推荐查看天气:https://www.0dtq.com/zhaoan/zuotian.html 推荐查看天气:https://www.0dtq.com/zhaoan/7tian.html 推荐查看天气:https://www.0dtq.com/zhaoan/10tian.html 推荐查看天气:https://www.0dtq.com/zhaoan/15tian.html 推荐查看天气:https://www.0dtq.com/zhaoan/40tian.html 推荐查看天气:https://www.0dtq.com/changtai/ 推荐查看天气:https://www.0dtq.com/changtai/zuotian.html 推荐查看天气:https://www.0dtq.com/changtai/7tian.html 推荐查看天气:https://www.0dtq.com/changtai/10tian.html 推荐查看天气:https://www.0dtq.com/changtai/15tian.html 推荐查看天气:https://www.0dtq.com/changtai/40tian.html 推荐查看天气:https://www.0dtq.com/zhangzhoudongshan/ 推荐查看天气:https://www.0dtq.com/zhangzhoudongshan/zuotian.html 推荐查看天气:https://www.0dtq.com/zhangzhoudongshan/7tian.html 推荐查看天气:https://www.0dtq.com/zhangzhoudongshan/10tian.html 推荐查看天气:https://www.0dtq.com/zhangzhoudongshan/15tian.html 推荐查看天气:https://www.0dtq.com/zhangzhoudongshan/40tian.html 推荐查看天气:https://www.0dtq.com/nanjingxian/ 推荐查看天气:https://www.0dtq.com/nanjingxian/zuotian.html 推荐查看天气:https://www.0dtq.com/nanjingxian/7tian.html 推荐查看天气:https://www.0dtq.com/nanjingxian/10tian.html 推荐查看天气:https://www.0dtq.com/nanjingxian/15tian.html 推荐查看天气:https://www.0dtq.com/nanjingxian/40tian.html 推荐查看天气:https://www.0dtq.com/pinghe/ 推荐查看天气:https://www.0dtq.com/pinghe/zuotian.html 推荐查看天气:https://www.0dtq.com/pinghe/7tian.html 推荐查看天气:https://www.0dtq.com/pinghe/10tian.html 推荐查看天气:https://www.0dtq.com/pinghe/15tian.html 推荐查看天气:https://www.0dtq.com/pinghe/40tian.html 推荐查看天气:https://www.0dtq.com/huaan/ 推荐查看天气:https://www.0dtq.com/huaan/zuotian.html 推荐查看天气:https://www.0dtq.com/huaan/7tian.html 推荐查看天气:https://www.0dtq.com/huaan/10tian.html 推荐查看天气:https://www.0dtq.com/huaan/15tian.html 推荐查看天气:https://www.0dtq.com/huaan/40tian.html 推荐查看天气:https://www.0dtq.com/longhai/ 推荐查看天气:https://www.0dtq.com/longhai/zuotian.html 推荐查看天气:https://www.0dtq.com/longhai/7tian.html 推荐查看天气:https://www.0dtq.com/longhai/10tian.html 推荐查看天气:https://www.0dtq.com/longhai/15tian.html 推荐查看天气:https://www.0dtq.com/longhai/40tian.html 推荐查看天气:https://www.0dtq.com/nanping/ 推荐查看天气:https://www.0dtq.com/nanping/zuotian.html 推荐查看天气:https://www.0dtq.com/nanping/7tian.html 推荐查看天气:https://www.0dtq.com/nanping/10tian.html 推荐查看天气:https://www.0dtq.com/nanping/15tian.html 推荐查看天气:https://www.0dtq.com/nanping/40tian.html 推荐查看天气:https://www.0dtq.com/yanping/ 推荐查看天气:https://www.0dtq.com/yanping/zuotian.html 推荐查看天气:https://www.0dtq.com/yanping/7tian.html 推荐查看天气:https://www.0dtq.com/yanping/10tian.html 推荐查看天气:https://www.0dtq.com/yanping/15tian.html 推荐查看天气:https://www.0dtq.com/yanping/40tian.html 推荐查看天气:https://www.0dtq.com/shunchang/ 推荐查看天气:https://www.0dtq.com/shunchang/zuotian.html 推荐查看天气:https://www.0dtq.com/shunchang/7tian.html 推荐查看天气:https://www.0dtq.com/shunchang/10tian.html 推荐查看天气:https://www.0dtq.com/shunchang/15tian.html 推荐查看天气:https://www.0dtq.com/shunchang/40tian.html 推荐查看天气:https://www.0dtq.com/nanpingpucheng/ 推荐查看天气:https://www.0dtq.com/nanpingpucheng/zuotian.html 推荐查看天气:https://www.0dtq.com/nanpingpucheng/7tian.html 推荐查看天气:https://www.0dtq.com/nanpingpucheng/10tian.html 推荐查看天气:https://www.0dtq.com/nanpingpucheng/15tian.html 推荐查看天气:https://www.0dtq.com/nanpingpucheng/40tian.html 推荐查看天气:https://www.0dtq.com/guangze/ 推荐查看天气:https://www.0dtq.com/guangze/zuotian.html 推荐查看天气:https://www.0dtq.com/guangze/7tian.html 推荐查看天气:https://www.0dtq.com/guangze/10tian.html 推荐查看天气:https://www.0dtq.com/guangze/15tian.html 推荐查看天气:https://www.0dtq.com/guangze/40tian.html 推荐查看天气:https://www.0dtq.com/songxi/ 推荐查看天气:https://www.0dtq.com/songxi/zuotian.html 推荐查看天气:https://www.0dtq.com/songxi/7tian.html 推荐查看天气:https://www.0dtq.com/songxi/10tian.html 推荐查看天气:https://www.0dtq.com/songxi/15tian.html 推荐查看天气:https://www.0dtq.com/songxi/40tian.html 推荐查看天气:https://www.0dtq.com/zhenghe/ 推荐查看天气:https://www.0dtq.com/zhenghe/zuotian.html 推荐查看天气:https://www.0dtq.com/zhenghe/7tian.html 推荐查看天气:https://www.0dtq.com/zhenghe/10tian.html 推荐查看天气:https://www.0dtq.com/zhenghe/15tian.html 推荐查看天气:https://www.0dtq.com/zhenghe/40tian.html 推荐查看天气:https://www.0dtq.com/shaowu/ 推荐查看天气:https://www.0dtq.com/shaowu/zuotian.html 推荐查看天气:https://www.0dtq.com/shaowu/7tian.html 推荐查看天气:https://www.0dtq.com/shaowu/10tian.html 推荐查看天气:https://www.0dtq.com/shaowu/15tian.html 推荐查看天气:https://www.0dtq.com/shaowu/40tian.html 推荐查看天气:https://www.0dtq.com/wuyishan/ 推荐查看天气:https://www.0dtq.com/wuyishan/zuotian.html 推荐查看天气:https://www.0dtq.com/wuyishan/7tian.html 推荐查看天气:https://www.0dtq.com/wuyishan/10tian.html 推荐查看天气:https://www.0dtq.com/wuyishan/15tian.html 推荐查看天气:https://www.0dtq.com/wuyishan/40tian.html 推荐查看天气:https://www.0dtq.com/jianou/ 推荐查看天气:https://www.0dtq.com/jianou/zuotian.html 推荐查看天气:https://www.0dtq.com/jianou/7tian.html 推荐查看天气:https://www.0dtq.com/jianou/10tian.html 推荐查看天气:https://www.0dtq.com/jianou/15tian.html 推荐查看天气:https://www.0dtq.com/jianou/40tian.html 推荐查看天气:https://www.0dtq.com/jianyang/ 推荐查看天气:https://www.0dtq.com/jianyang/zuotian.html 推荐查看天气:https://www.0dtq.com/jianyang/7tian.html 推荐查看天气:https://www.0dtq.com/jianyang/10tian.html 推荐查看天气:https://www.0dtq.com/jianyang/15tian.html 推荐查看天气:https://www.0dtq.com/jianyang/40tian.html 推荐查看天气:https://www.0dtq.com/longyan/ 推荐查看天气:https://www.0dtq.com/longyan/zuotian.html

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册