[{"data":1,"prerenderedAt":1261},["ShallowReactive",2],{"docsNavigation":3,"blogNavigation":53,"/blog/number-scroll-animation":95,"/blog/number-scroll-animation-surround":1256},[4,38],{"title":5,"path":6,"stem":7,"children":8,"icon":37},"常用网站","/docs/getting-started","1.docs/1.getting-started/1.index",[9,12,17,22,27,32],{"title":10,"path":6,"stem":7,"icon":11},"区块链相关(前端)","i-lucide-box",{"title":13,"path":14,"stem":15,"icon":16},"图片压缩","/docs/getting-started/photo-compression","1.docs/1.getting-started/2.photo-compression","i-lucide-image",{"title":18,"path":19,"stem":20,"icon":21},"组件库","/docs/getting-started/component-library","1.docs/1.getting-started/3.component-library","i-lucide-puzzle",{"title":23,"path":24,"stem":25,"icon":26},"图表库","/docs/getting-started/charts","1.docs/1.getting-started/4.charts","i-lucide-bar-chart-3",{"title":28,"path":29,"stem":30,"icon":31},"CSS","/docs/getting-started/css","1.docs/1.getting-started/5.css","i-lucide-palette",{"title":33,"path":34,"stem":35,"icon":36},"调试测试工具","/docs/getting-started/test","1.docs/1.getting-started/6.test","i-lucide-bug",false,{"title":39,"path":40,"stem":41,"children":42,"page":37},"常用工具","/docs/essentials","1.docs/2.essentials",[43,48],{"title":44,"path":45,"stem":46,"icon":47},"uni-helper","/docs/essentials/uni-helper","1.docs/2.essentials/1.uni-helper","i-lucide-settings",{"title":49,"path":50,"stem":51,"icon":52},"工作流可视化库","/docs/essentials/workflow-libraries","1.docs/2.essentials/2.workflow-libraries","i-lucide-workflow",[54],{"title":55,"path":56,"stem":57,"children":58,"page":37},"Blog","/blog","3.blog",[59,63,67,71,75,79,83,87,91],{"title":60,"path":61,"stem":62},"Vue 3 中 \u003CTransition> 报错：组件根节点无法被动画化的解决方案","/blog/asian-cuisine","3.blog/1.asian-cuisine",{"title":64,"path":65,"stem":66},"使用 openapi-ts-request 自动生成 API 请求代码","/blog/apifox-api-generation","3.blog/2.apifox-api-generation",{"title":68,"path":69,"stem":70},"解决 uni.upload 多文件上传限制：使用 fetch + FormData 实现 H5 环境下的多文件上传","/blog/file-upload-issue-solution","3.blog/3.file-upload-issue-solution",{"title":72,"path":73,"stem":74},"Wangeditor中被div包裹的img标签被过滤问题解决方案","/blog/wangeditor-img-filter-issue","3.blog/4.wangeditor-img-filter-issue",{"title":76,"path":77,"stem":78},"Nuxt项目部署后报错 “Cannot load payload /_payload.json” 的修复","/blog/nuxt-payload-extraction","3.blog/5.nuxt-payload-extraction",{"title":80,"path":81,"stem":82},"Nuxt项目导入nuxt-echarts实现图表渲染","/blog/nuxt-echarts-implementation","3.blog/6.nuxt-echarts-implementation",{"title":84,"path":85,"stem":86},"Reown+Wagmi 在 UniApp+Vite 项目中的问题与解决方案","/blog/reown-wagmi-uniapp-issues","3.blog/7.reown-wagmi-uniapp-issues",{"title":88,"path":89,"stem":90},"数字滚动动画组件 - Vue 动画最佳实践","/blog/number-scroll-animation","3.blog/8.number-scroll-animation",{"title":92,"path":93,"stem":94},"新电脑安装 nvm 卡住？无需修改配置文件，一行命令完美解决！","/blog/nvm-install-solution","3.blog/9.nvm-install-solution",{"id":96,"title":88,"authors":97,"badge":102,"body":104,"date":1248,"description":1249,"extension":1250,"image":1251,"meta":1253,"navigation":350,"path":89,"seo":1254,"stem":90,"__hash__":1255},"posts/3.blog/8.number-scroll-animation.md",[98],{"name":99,"avatar":100},"qibmz",{"src":101},"/image/avatar.avif",{"label":103},"Vue3",{"type":105,"value":106,"toc":1228},"minimark",[107,111,115,118,121,137,140,143,166,173,183,186,189,198,285,289,495,499,502,795,799,854,857,871,874,884,887,898,901,921,924,998,1001,1009,1012,1026,1031,1034,1038,1103,1107,1152,1156,1189,1192,1197,1219,1225],[108,109,110],"h2",{"id":110},"概述",[112,113,114],"p",{},"数字滚动动画常见于数据大屏、计数器、统计面板。本文按「需求 -> 原理 -> 实现 -> 性能 -> 实战」的顺序，带你完成一个高性能、可复用、内存友好的 Vue 3 数字滚动组件。",[108,116,117],{"id":117},"先明确目标",[112,119,120],{},"设计一个数字滚动组件，要求：",[122,123,124,128,131,134],"ul",{},[125,126,127],"li",{},"📊 支持整数、小数、负数",[125,129,130],{},"⚡ 动画流畅，视觉反馈自然",[125,132,133],{},"🎯 高性能，避免频繁更新时卡顿",[125,135,136],{},"🔄 内存安全，杜绝定时器堆积与泄漏",[108,138,139],{"id":139},"实现原理",[112,141,142],{},"数字滚动的本质是「逐位滚动」：",[122,144,145,148,156],{},[125,146,147],{},"每一位数字都是 0-9 垂直排列",[125,149,150,151,155],{},"通过 ",[152,153,154],"code",{},"translateY"," 改变可视窗口中的数字",[125,157,158,159,162,163],{},"数字 ",[152,160,161],{},"N"," 的偏移量是 ",[152,164,165],{},"N * -100%",[112,167,168,169,172],{},"例如显示数字 ",[152,170,171],{},"5","：",[174,175,180],"pre",{"className":176,"code":178,"language":179},[177],"language-text","0  ← translateY: 0%\n1\n2\n3\n4\n5  ← translateY: -500% (当前显示)\n6\n7\n8\n9\n","text",[152,181,178],{"__ignoreMap":182},"",[112,184,185],{},"理解这个映射关系后，再看代码会非常直接。",[108,187,188],{"id":188},"核心实现要点",[190,191,193,194,197],"h3",{"id":192},"_1-使用-transform-做位移动画","1. 使用 ",[152,195,196],{},"transform"," 做位移动画",[199,200,201,257],"code-group",{},[174,202,207],{"className":203,"code":204,"filename":205,"language":206,"meta":182,"style":182},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// 修改 margin 或 top 会触发布局重排\nstyle.marginTop = value;\nstyle.top = value;\n","❌ 不推荐","ts",[152,208,209,218,241],{"__ignoreMap":182},[210,211,214],"span",{"class":212,"line":213},"line",1,[210,215,217],{"class":216},"sHwdD","// 修改 margin 或 top 会触发布局重排\n",[210,219,221,225,229,232,235,238],{"class":212,"line":220},2,[210,222,224],{"class":223},"sTEyZ","style",[210,226,228],{"class":227},"sMK4o",".",[210,230,231],{"class":223},"marginTop ",[210,233,234],{"class":227},"=",[210,236,237],{"class":223}," value",[210,239,240],{"class":227},";\n",[210,242,244,246,248,251,253,255],{"class":212,"line":243},3,[210,245,224],{"class":223},[210,247,228],{"class":227},[210,249,250],{"class":223},"top ",[210,252,234],{"class":227},[210,254,237],{"class":223},[210,256,240],{"class":227},[174,258,261],{"className":203,"code":259,"filename":260,"language":206,"meta":182,"style":182},"// transform 更容易走 GPU 合成层，动画更稳定\n:style=\"{ transform: `translateY(${value}%)` }\"\n","✅ 推荐",[152,262,263,268],{"__ignoreMap":182},[210,264,265],{"class":212,"line":213},[210,266,267],{"class":216},"// transform 更容易走 GPU 合成层，动画更稳定\n",[210,269,270,273,275,278,282],{"class":212,"line":220},[210,271,272],{"class":223},":style",[210,274,234],{"class":227},[210,276,277],{"class":227},"\"",[210,279,281],{"class":280},"sfazB","{ transform: `translateY(${value}%)` }",[210,283,284],{"class":227},"\"\n",[190,286,288],{"id":287},"_2-用计算属性拆分字符并计算位移","2. 用计算属性拆分字符并计算位移",[174,290,292],{"className":203,"code":291,"language":206,"meta":182,"style":182},"// 字符串转数组，用于逐位显示\nconst displayedChars = computed(() => targetValue.value.split(\"\"));\n\n// 计算每一位的偏移距离\nconst getTranslateY = (char: string): string => {\n  if (char === \".\") return \"0\";\n  const digit = parseInt(char, 10);\n  return digit * -100 + \"%\";\n};\n",[152,293,294,299,346,352,358,392,429,460,489],{"__ignoreMap":182},[210,295,296],{"class":212,"line":213},[210,297,298],{"class":216},"// 字符串转数组，用于逐位显示\n",[210,300,301,305,308,310,314,317,320,323,326,328,331,333,336,338,341,344],{"class":212,"line":220},[210,302,304],{"class":303},"spNyl","const",[210,306,307],{"class":223}," displayedChars ",[210,309,234],{"class":227},[210,311,313],{"class":312},"s2Zo4"," computed",[210,315,316],{"class":223},"(",[210,318,319],{"class":227},"()",[210,321,322],{"class":303}," =>",[210,324,325],{"class":223}," targetValue",[210,327,228],{"class":227},[210,329,330],{"class":223},"value",[210,332,228],{"class":227},[210,334,335],{"class":312},"split",[210,337,316],{"class":223},[210,339,340],{"class":227},"\"\"",[210,342,343],{"class":223},"))",[210,345,240],{"class":227},[210,347,348],{"class":212,"line":243},[210,349,351],{"emptyLinePlaceholder":350},true,"\n",[210,353,355],{"class":212,"line":354},4,[210,356,357],{"class":216},"// 计算每一位的偏移距离\n",[210,359,361,363,366,368,371,375,378,382,385,387,389],{"class":212,"line":360},5,[210,362,304],{"class":303},[210,364,365],{"class":223}," getTranslateY ",[210,367,234],{"class":227},[210,369,370],{"class":227}," (",[210,372,374],{"class":373},"sHdIc","char",[210,376,377],{"class":227},":",[210,379,381],{"class":380},"sBMFI"," string",[210,383,384],{"class":227},"):",[210,386,381],{"class":380},[210,388,322],{"class":303},[210,390,391],{"class":227}," {\n",[210,393,395,399,402,404,407,410,412,414,417,420,422,425,427],{"class":212,"line":394},6,[210,396,398],{"class":397},"s7zQu","  if",[210,400,370],{"class":401},"swJcz",[210,403,374],{"class":223},[210,405,406],{"class":227}," ===",[210,408,409],{"class":227}," \"",[210,411,228],{"class":280},[210,413,277],{"class":227},[210,415,416],{"class":401},") ",[210,418,419],{"class":397},"return",[210,421,409],{"class":227},[210,423,424],{"class":280},"0",[210,426,277],{"class":227},[210,428,240],{"class":227},[210,430,432,435,438,441,444,446,448,451,455,458],{"class":212,"line":431},7,[210,433,434],{"class":303},"  const",[210,436,437],{"class":223}," digit",[210,439,440],{"class":227}," =",[210,442,443],{"class":312}," parseInt",[210,445,316],{"class":401},[210,447,374],{"class":223},[210,449,450],{"class":227},",",[210,452,454],{"class":453},"sbssI"," 10",[210,456,457],{"class":401},")",[210,459,240],{"class":227},[210,461,463,466,468,471,474,477,480,482,485,487],{"class":212,"line":462},8,[210,464,465],{"class":397},"  return",[210,467,437],{"class":223},[210,469,470],{"class":227}," *",[210,472,473],{"class":227}," -",[210,475,476],{"class":453},"100",[210,478,479],{"class":227}," +",[210,481,409],{"class":227},[210,483,484],{"class":280},"%",[210,486,277],{"class":227},[210,488,240],{"class":227},[210,490,492],{"class":212,"line":491},9,[210,493,494],{"class":227},"};\n",[190,496,498],{"id":497},"_3-管理定时器避免快速更新时堆积","3. 管理定时器，避免快速更新时堆积",[112,500,501],{},"定时器未清理是常见内存泄漏来源，尤其在高频数据更新场景中。",[174,503,505],{"className":203,"code":504,"language":206,"meta":182,"style":182},"// ❌ 问题代码\nwatch(\n  () => props.value,\n  () => {\n    setTimeout(() => updateValue(), 1000); // 快速更新时会堆积多个 timer\n  },\n);\n\n// ✅ 正确做法\nlet timerId: ReturnType\u003Ctypeof setTimeout> | null = null;\n\nconst clearTimer = () => {\n  if (timerId) clearTimeout(timerId);\n};\n\nwatch(\n  () => props.value,\n  () => {\n    clearTimer(); // 先清理旧 timer\n    timerId = setTimeout(() => updateValue(), 1000);\n  },\n);\n\nonUnmounted(() => clearTimer()); // 卸载时清理\n",[152,506,507,512,520,537,545,574,579,585,589,594,628,633,650,673,678,683,690,705,714,727,755,760,767,772],{"__ignoreMap":182},[210,508,509],{"class":212,"line":213},[210,510,511],{"class":216},"// ❌ 问题代码\n",[210,513,514,517],{"class":212,"line":220},[210,515,516],{"class":312},"watch",[210,518,519],{"class":223},"(\n",[210,521,522,525,527,530,532,534],{"class":212,"line":243},[210,523,524],{"class":227},"  ()",[210,526,322],{"class":303},[210,528,529],{"class":223}," props",[210,531,228],{"class":227},[210,533,330],{"class":223},[210,535,536],{"class":227},",\n",[210,538,539,541,543],{"class":212,"line":354},[210,540,524],{"class":227},[210,542,322],{"class":303},[210,544,391],{"class":227},[210,546,547,550,552,554,556,559,561,563,566,568,571],{"class":212,"line":360},[210,548,549],{"class":312},"    setTimeout",[210,551,316],{"class":401},[210,553,319],{"class":227},[210,555,322],{"class":303},[210,557,558],{"class":312}," updateValue",[210,560,319],{"class":401},[210,562,450],{"class":227},[210,564,565],{"class":453}," 1000",[210,567,457],{"class":401},[210,569,570],{"class":227},";",[210,572,573],{"class":216}," // 快速更新时会堆积多个 timer\n",[210,575,576],{"class":212,"line":394},[210,577,578],{"class":227},"  },\n",[210,580,581,583],{"class":212,"line":431},[210,582,457],{"class":223},[210,584,240],{"class":227},[210,586,587],{"class":212,"line":462},[210,588,351],{"emptyLinePlaceholder":350},[210,590,591],{"class":212,"line":491},[210,592,593],{"class":216},"// ✅ 正确做法\n",[210,595,597,600,603,605,608,611,614,617,620,623,625],{"class":212,"line":596},10,[210,598,599],{"class":303},"let",[210,601,602],{"class":223}," timerId",[210,604,377],{"class":227},[210,606,607],{"class":380}," ReturnType",[210,609,610],{"class":227},"\u003Ctypeof",[210,612,613],{"class":223}," setTimeout",[210,615,616],{"class":227},">",[210,618,619],{"class":227}," |",[210,621,622],{"class":380}," null",[210,624,440],{"class":227},[210,626,627],{"class":227}," null;\n",[210,629,631],{"class":212,"line":630},11,[210,632,351],{"emptyLinePlaceholder":350},[210,634,636,638,641,643,646,648],{"class":212,"line":635},12,[210,637,304],{"class":303},[210,639,640],{"class":223}," clearTimer ",[210,642,234],{"class":227},[210,644,645],{"class":227}," ()",[210,647,322],{"class":303},[210,649,391],{"class":227},[210,651,653,655,657,660,662,665,667,669,671],{"class":212,"line":652},13,[210,654,398],{"class":397},[210,656,370],{"class":401},[210,658,659],{"class":223},"timerId",[210,661,416],{"class":401},[210,663,664],{"class":312},"clearTimeout",[210,666,316],{"class":401},[210,668,659],{"class":223},[210,670,457],{"class":401},[210,672,240],{"class":227},[210,674,676],{"class":212,"line":675},14,[210,677,494],{"class":227},[210,679,681],{"class":212,"line":680},15,[210,682,351],{"emptyLinePlaceholder":350},[210,684,686,688],{"class":212,"line":685},16,[210,687,516],{"class":312},[210,689,519],{"class":223},[210,691,693,695,697,699,701,703],{"class":212,"line":692},17,[210,694,524],{"class":227},[210,696,322],{"class":303},[210,698,529],{"class":223},[210,700,228],{"class":227},[210,702,330],{"class":223},[210,704,536],{"class":227},[210,706,708,710,712],{"class":212,"line":707},18,[210,709,524],{"class":227},[210,711,322],{"class":303},[210,713,391],{"class":227},[210,715,717,720,722,724],{"class":212,"line":716},19,[210,718,719],{"class":312},"    clearTimer",[210,721,319],{"class":401},[210,723,570],{"class":227},[210,725,726],{"class":216}," // 先清理旧 timer\n",[210,728,730,733,735,737,739,741,743,745,747,749,751,753],{"class":212,"line":729},20,[210,731,732],{"class":223},"    timerId",[210,734,440],{"class":227},[210,736,613],{"class":312},[210,738,316],{"class":401},[210,740,319],{"class":227},[210,742,322],{"class":303},[210,744,558],{"class":312},[210,746,319],{"class":401},[210,748,450],{"class":227},[210,750,565],{"class":453},[210,752,457],{"class":401},[210,754,240],{"class":227},[210,756,758],{"class":212,"line":757},21,[210,759,578],{"class":227},[210,761,763,765],{"class":212,"line":762},22,[210,764,457],{"class":223},[210,766,240],{"class":227},[210,768,770],{"class":212,"line":769},23,[210,771,351],{"emptyLinePlaceholder":350},[210,773,775,778,780,782,784,787,790,792],{"class":212,"line":774},24,[210,776,777],{"class":312},"onUnmounted",[210,779,316],{"class":223},[210,781,319],{"class":227},[210,783,322],{"class":303},[210,785,786],{"class":312}," clearTimer",[210,788,789],{"class":223},"())",[210,791,570],{"class":227},[210,793,794],{"class":216}," // 卸载时清理\n",[190,796,798],{"id":797},"_4-用贝塞尔曲线优化体感","4. 用贝塞尔曲线优化体感",[174,800,802],{"className":203,"code":801,"language":206,"meta":182,"style":182},"// cubic-bezier(0.34, 1.56, 0.64, 1) 有轻微弹性回落效果\ntransition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n",[152,803,804,809],{"__ignoreMap":182},[210,805,806],{"class":212,"line":213},[210,807,808],{"class":216},"// cubic-bezier(0.34, 1.56, 0.64, 1) 有轻微弹性回落效果\n",[210,810,811,814,816,819,821,824,827,830,832,835,837,840,842,845,847,850,852],{"class":212,"line":220},[210,812,813],{"class":380},"transition",[210,815,377],{"class":227},[210,817,818],{"class":223}," transform 0",[210,820,228],{"class":227},[210,822,823],{"class":223},"3s cubic",[210,825,826],{"class":227},"-",[210,828,829],{"class":312},"bezier",[210,831,316],{"class":223},[210,833,834],{"class":453},"0.34",[210,836,450],{"class":227},[210,838,839],{"class":453}," 1.56",[210,841,450],{"class":227},[210,843,844],{"class":453}," 0.64",[210,846,450],{"class":227},[210,848,849],{"class":453}," 1",[210,851,457],{"class":223},[210,853,240],{"class":227},[112,855,856],{},"参数含义：",[122,858,859,865],{},[125,860,861,864],{},[152,862,863],{},"0.34, 1.56","：前半段加速并略微超调",[125,866,867,870],{},[152,868,869],{},"0.64, 1","：后半段回落并稳定停住",[108,872,873],{"id":873},"完整组件与特性",[112,875,876,883],{},[877,878,882],"a",{"href":879,"rel":880},"https://github.com/qibmz/blog/blob/main/app/components/demo/NumberScroll.vue",[881],"nofollow","NumberScroll.vue","：可复用的高性能数字滚动组件。",[112,885,886],{},"技术栈：",[122,888,889,892,895],{},[125,890,891],{},"Vue 3 Composition API",[125,893,894],{},"TypeScript",[125,896,897],{},"Tailwind CSS（无需 SCSS）",[112,899,900],{},"关键特性：",[122,902,903,906,909,912,915,918],{},[125,904,905],{},"✅ 自动清理定时器，无内存泄漏",[125,907,908],{},"✅ 支持小数点和负数",[125,910,911],{},"✅ 使用 GPU 友好的 transform 动画",[125,913,914],{},"✅ 快速更新时自动取消旧动画",[125,916,917],{},"✅ 无外部依赖，样式可直接复用",[125,919,920],{},"✅ 支持自定义动画时长",[108,922,923],{"id":923},"性能对比",[925,926,927,946],"table",{},[928,929,930],"thead",{},[931,932,933,937,940,943],"tr",{},[934,935,936],"th",{},"实现方式",[934,938,939],{},"FPS",[934,941,942],{},"内存泄漏",[934,944,945],{},"响应性",[947,948,949,964,976],"tbody",{},[931,950,951,955,958,961],{},[952,953,954],"td",{},"margin 修改",[952,956,957],{},"30-45",[952,959,960],{},"有",[952,962,963],{},"⚠️ 中等",[931,965,966,969,972,974],{},[952,967,968],{},"position 修改",[952,970,971],{},"45-55",[952,973,960],{},[952,975,963],{},[931,977,978,983,988,993],{},[952,979,980],{},[981,982,196],"strong",{},[952,984,985],{},[981,986,987],{},"55-60",[952,989,990],{},[981,991,992],{},"无",[952,994,995],{},[981,996,997],{},"✅ 优秀",[108,999,1000],{"id":1000},"在线演示",[112,1002,1003,1004,1008],{},"完整交互式演示请访问 ",[877,1005,1007],{"href":1006},"/playground/number-scroll","🎮 数字滚动动画试炼场","。",[112,1010,1011],{},"你可以在试炼场中：",[122,1013,1014,1017,1020,1023],{},[125,1015,1016],{},"📊 实时观察滚动效果",[125,1018,1019],{},"🎮 切换不同数据场景",[125,1021,1022],{},"📈 对比不同实现策略",[125,1024,1025],{},"🔧 体验组件配置项",[112,1027,1028],{},[877,1029,1030],{"href":1006},"前往试炼场 →",[108,1032,1033],{"id":1033},"常见问题",[190,1035,1037],{"id":1036},"q1-如何处理负数","Q1: 如何处理负数？",[174,1039,1041],{"className":203,"code":1040,"language":206,"meta":182,"style":182},"// 可以在前面加符号\nconst displayValue = value \u003C 0 ? `-${Math.abs(value)}` : `${value}`;\n",[152,1042,1043,1048],{"__ignoreMap":182},[210,1044,1045],{"class":212,"line":213},[210,1046,1047],{"class":216},"// 可以在前面加符号\n",[210,1049,1050,1052,1055,1057,1060,1063,1066,1069,1072,1074,1077,1080,1082,1085,1088,1091,1094,1097,1099,1101],{"class":212,"line":220},[210,1051,304],{"class":303},[210,1053,1054],{"class":223}," displayValue ",[210,1056,234],{"class":227},[210,1058,1059],{"class":223}," value ",[210,1061,1062],{"class":227},"\u003C",[210,1064,1065],{"class":453}," 0",[210,1067,1068],{"class":227}," ?",[210,1070,1071],{"class":227}," `",[210,1073,826],{"class":280},[210,1075,1076],{"class":227},"${",[210,1078,1079],{"class":223},"Math",[210,1081,228],{"class":227},[210,1083,1084],{"class":312},"abs",[210,1086,1087],{"class":223},"(value)",[210,1089,1090],{"class":227},"}`",[210,1092,1093],{"class":227}," :",[210,1095,1096],{"class":227}," `${",[210,1098,330],{"class":223},[210,1100,1090],{"class":227},[210,1102,240],{"class":227},[190,1104,1106],{"id":1105},"q2-动画总是要-03s-吗","Q2: 动画总是要 0.3s 吗？",[174,1108,1110],{"className":203,"code":1109,"language":206,"meta":182,"style":182},"// 可以通过 duration prop 自定义\n\u003CNumberScroll :value=\"num\" :duration=\"500\" />\n",[152,1111,1112,1117],{"__ignoreMap":182},[210,1113,1114],{"class":212,"line":213},[210,1115,1116],{"class":216},"// 可以通过 duration prop 自定义\n",[210,1118,1119,1121,1124,1126,1128,1130,1132,1135,1137,1140,1142,1144,1147,1149],{"class":212,"line":220},[210,1120,1062],{"class":227},[210,1122,1123],{"class":380},"NumberScroll",[210,1125,1093],{"class":227},[210,1127,330],{"class":223},[210,1129,234],{"class":227},[210,1131,277],{"class":227},[210,1133,1134],{"class":280},"num",[210,1136,277],{"class":227},[210,1138,1139],{"class":223}," :duration",[210,1141,234],{"class":227},[210,1143,277],{"class":227},[210,1145,1146],{"class":280},"500",[210,1148,277],{"class":227},[210,1150,1151],{"class":227}," />\n",[190,1153,1155],{"id":1154},"q3-如何添加千位分隔符","Q3: 如何添加千位分隔符？",[174,1157,1159],{"className":203,"code":1158,"language":206,"meta":182,"style":182},"const formatted = value.toLocaleString(); // 1,234,567\n// 然后显示格式化后的字符串\n",[152,1160,1161,1184],{"__ignoreMap":182},[210,1162,1163,1165,1168,1170,1172,1174,1177,1179,1181],{"class":212,"line":213},[210,1164,304],{"class":303},[210,1166,1167],{"class":223}," formatted ",[210,1169,234],{"class":227},[210,1171,237],{"class":223},[210,1173,228],{"class":227},[210,1175,1176],{"class":312},"toLocaleString",[210,1178,319],{"class":223},[210,1180,570],{"class":227},[210,1182,1183],{"class":216}," // 1,234,567\n",[210,1185,1186],{"class":212,"line":220},[210,1187,1188],{"class":216},"// 然后显示格式化后的字符串\n",[1190,1191],"hr",{},[112,1193,1194],{},[981,1195,1196],{},"相关资源：",[122,1198,1199,1205,1212],{},[125,1200,1201],{},[877,1202,891],{"href":1203,"rel":1204},"https://vuejs.org/guide/extras/composition-api-faq.html",[881],[125,1206,1207],{},[877,1208,1211],{"href":1209,"rel":1210},"https://web.dev/animations-guide/",[881],"CSS transform 性能",[125,1213,1214],{},[877,1215,1218],{"href":1216,"rel":1217},"https://cubic-bezier.com/",[881],"贝塞尔曲线可视化",[1220,1221,1222],"blockquote",{},[112,1223,1224],{},"（注：文档内容由 Copilot 生成）",[224,1226,1227],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":182,"searchDepth":220,"depth":220,"links":1229},[1230,1231,1232,1233,1240,1241,1242,1243],{"id":110,"depth":220,"text":110},{"id":117,"depth":220,"text":117},{"id":139,"depth":220,"text":139},{"id":188,"depth":220,"text":188,"children":1234},[1235,1237,1238,1239],{"id":192,"depth":243,"text":1236},"1. 使用 transform 做位移动画",{"id":287,"depth":243,"text":288},{"id":497,"depth":243,"text":498},{"id":797,"depth":243,"text":798},{"id":873,"depth":220,"text":873},{"id":923,"depth":220,"text":923},{"id":1000,"depth":220,"text":1000},{"id":1033,"depth":220,"text":1033,"children":1244},[1245,1246,1247],{"id":1036,"depth":243,"text":1037},{"id":1105,"depth":243,"text":1106},{"id":1154,"depth":243,"text":1155},"2026-02-05T00:00:00.000Z","详解如何用 Vue 3 Composition API 实现高性能的数字滚动动画组件，包含内存优化、性能调优和完整代码实现。","md",{"src":1252},"https://picsum.photos/id/103/640/360",{},{"title":88,"description":1249},"_cxhunoSkiHU4oKCsGxXYdzaokT6ckWzDJrJvIPF-t0",[1257,1259],{"title":84,"path":85,"stem":86,"description":1258,"children":-1},"在 UniApp+Vite 框架中集成 Reown 和 Wagmi 时遇到的打包、兼容性、RPC 访问等常见问题及完整解决方案。",{"title":92,"path":93,"stem":94,"description":1260,"children":-1},"安装 nvm-windows 后下载 Node.js 卡住？无需手动修改 settings.txt，使用 nvm 内置命令切换淘宝镜像或配置代理，一行命令即可解决。",1774239528092]