大家好,我是子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向:前端 / 跨端 / 小程序 / 移动端工程化
内容平台:掘金、知乎、CSDN、简书
创作特点:实战导向、源码拆解、少空谈多落地
文章状态:长期稳定更新,大量原创输出
我的内容主要围绕前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取11 类前端进阶学习资源(工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学“明白”,也用“到位”
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
- 引言
- 一、为什么会出现“巨型页面”?
- 核心原因:职责没有拆分
- 二、正确拆分思路
- 一句话原则:
- 正确结构:
- 三、第一步:拆 Service
- 页面写逻辑
- 提取到 Service
- 页面变成:
- 四、第二步:拆 Store
- 页面管理状态
- 统一 Store
- 页面只读:
- 五、第三步:拆组件
- 页面 UI 堆积
- 拆组件
- 页面使用:
- 六、第四步:拆网络
- 页面直接 fetch
- Service 调用
- 七、第五步:引入模块化
- 推荐结构
- 八、最终页面应该长什么样?
- 理想页面
- 九、判断标准
- 出现这些
- 正确状态
- 十、为什么这很重要?
- 1、可维护性
- 2、可扩展性
- 3、团队协作
- 4、避免“技术债”
- 总结
引言
如果你写过一段时间鸿蒙游戏,很可能已经遇到这个问题:
一个页面文件,越来越大。
最开始:
200 行后来变成:
800 行再后来:
2000 行 +而且你会发现:
- UI 写在一起
- 逻辑写在一起
- 网络写在一起
- 状态也写在一起
最后变成一个典型的:
“巨型页面文件(God Component)”
在 HarmonyOS 的 ArkUI 体系下,这个问题尤其常见。
一、为什么会出现“巨型页面”?
核心原因:职责没有拆分
一个典型错误页面:
@Entry@Componentstruct GamePage{@Statescore:number=0@Statelist:any[]=[]aboutToAppear(){this.loadData()}asyncloadData(){constres=awaitfetch("/api/list")this.list=awaitres.json()}movePlayer(){this.score+=1}build(){Column(){Text(`Score:${this.score}`)Button("移动").onClick(()=>this.movePlayer())ForEach(this.list,item=>{Text(item.name)})}}}看起来没问题,但其实混在一起了:
UI 状态 网络 逻辑一旦变复杂:
你会完全失控
二、正确拆分思路
一句话原则:
页面只负责 UI,其它全部拆出去
正确结构:
Page(UI) ↓ Service(逻辑) ↓ Store(状态) ↓ Network(数据)再加:
Component(UI拆分) Agent(AI)三、第一步:拆 Service
页面写逻辑
movePlayer(){this.score+=1}提取到 Service
// services/GameService.etsimport{gameStore}from'../store/GameStore'exportclassGameService{movePlayer(){gameStore.dispatch({type:'ADD_SCORE',payload:1})}}exportconstgameService=newGameService()页面变成:
Button("移动").onClick(()=>gameService.movePlayer())页面瞬间变干净。
四、第二步:拆 Store
页面管理状态
@Statescore:number=0统一 Store
// store/GameStore.etsexportclassGameStore{state={score:0}dispatch(action){if(action.type==='ADD_SCORE'){this.state.score+=action.payload}}}exportconstgameStore=newGameStore()页面只读:
@Statestate=gameStore.state页面不再“拥有状态”。
五、第三步:拆组件
页面 UI 堆积
Column(){Text("玩家")Image("avatar.png")Text("分数")}拆组件
// components/PlayerInfo.ets@Componentexportstruct PlayerInfo{@Propscore:numberbuild(){Column(){Text("玩家")Text(`分数:${this.score}`)}}}页面使用:
PlayerInfo({score:this.state.score})页面只负责“拼装 UI”。
六、第四步:拆网络
页面直接 fetch
awaitfetch("/api/list")Service 调用
awaitdataService.fetchList()页面完全不关心数据来源。
七、第五步:引入模块化
当游戏变大:
推荐结构
modules ├─ player │ ├─ PlayerService │ ├─ PlayerStore │ └─ PlayerComponent │ ├─ task ├─ battle原则:
按业务拆,而不是按技术层拆
八、最终页面应该长什么样?
理想页面
@Entry@Componentstruct GamePage{@Statestate=gameStore.statebuild(){Column(){PlayerInfo({score:this.state.score})Button("移动").onClick(()=>gameService.movePlayer())}}}页面只剩:
UI + 事件绑定这才是正确形态。
九、判断标准
如果你的页面:
出现这些
- 有 fetch
- 有复杂逻辑
- 有多层 if
- 有状态计算
说明已经“变胖了”。
正确状态
页面应该:
简单到可以一眼看懂十、为什么这很重要?
1、可维护性
逻辑在 Service 状态在 Store修改不会影响 UI。
2、可扩展性
你可以轻松加:
- AI
- 多端
- 网络
3、团队协作
UI开发 逻辑开发 AI开发可以分开做。
4、避免“技术债”
巨型页面的本质是:
技术债爆炸前兆
总结
避免“巨型页面文件”的核心方法:
1、逻辑进 Service 2、状态进 Store 3、UI 拆 Component 4、网络独立 5、按模块拆分在 HarmonyOS 的 ArkUI 架构中,这不是“优化建议”,而是:
必须遵守的架构规则