首页 / 资讯中心 / 文章详情

Kuikly鸿蒙开发训练营Day1:环境搭建与声明式UI状态驱动实战记录

Kuikly鸿蒙开发训练营Day1:环境搭建与声明式UI状态驱动实战记录 ★ FEATURED ARTICLE
寒假报了 Kuikly 鸿蒙开发训练营Day 1 刚结束趁脑子里的细节还热乎赶紧把这份笔记整理出来。先说结论如果你之前只会写 Web 页面又想进入鸿蒙生态Kuikly 是一个很舒服的入口因为它把 ArkUI 的复杂度包了一层写起来有点像平时写组件一样。今天全天做了四件事装好开发环境、了解 Kuikly 的定位、跑通第一个 Hello 工程、把状态和路由的基础过了一遍。下面的内容都是实际操作中验证过的记录不是官方文档的搬运。给后面几天的自己留个底也希望能帮到同期的同学。1. 训练营首日全景Kuikly 到底解决什么问题1.1 为什么不用纯 ArkUI非要套一层 Kuikly纯鸿蒙开发用 ArkTS ArkUI 其实也能写但门槛不低。第一天老师就抛出一个问题“如果你们团队之前主力是前端现在突然要交付一个鸿蒙应用你们打算从哪入手” 现场讨论了一会儿最后给出的答案就是 Kuikly。我的理解是Kuikly 把自己定位成鸿蒙生态里的一个“轻量级跨端 UI 层”它把 ArkUI 的很多细节封装成更贴近 Web 开发习惯的 API。比如你在 Web 框架里写组件、绑定事件、管理状态的那套思路到 Kuikly 里基本能复用不用去记 ArkUI 那套繁琐的链式属性写法。当然并不是说 Kuikly 可以完全替代 ArkUI。它更像是在 ArkUI 之上做了一层语义化封装最终编译时还是会落到鸿蒙的 ArkUI 组件树。换句话说Kuikly 帮你把“菜洗好切好”炒菜的火候还是控制在鸿蒙系统手里。这么做的好处很明显团队里熟悉 React/Vue 的同事可以快速上手同时项目后续如果需要做多端迁移底层的平台差异也被隔离掉了。训练营选 Kuikly大概就是看中了这套“低门槛 可落地”的组合拳。对比维度纯 ArkUI 开发Kuikly 开发学习曲线需要从头学 ArkTS 语法和 ArkUI 链式 API更接近 Web 组件化写法前端背景友好跨端能力只能跑在鸿蒙设备上设计上预留多端复用可能性状态管理需要手写大量链式刷新逻辑用 State 等装饰器声明即可排错体验报错信息偏底层封装层能提供更接近业务语义的报错1.2 Day 1 的课程节奏与目标先给大家一个全天的时间线参考。上午 9:00-10:30 是鸿蒙生态和训练营介绍老师简单讲了鸿蒙系统的分层结构、应用包形态以及 ArkTS 和 Kuikly 的关系10:45-12:00 大家跟着装环境基本上就是 DevEco Studio、SDK、命令行工具三件套下午 2:00-3:30 用 Kuikly 初始化了第一个工程3:45-5:30 重点讲了声明式 UI、状态管理和路由跳转最后半小时用来答疑和填坑。整体节奏不算快但信息密度很大尤其是下午那节如果之前完全没接触过声明式 UI可能需要课后多消化一下。Day 1 的目标很明确一是所有人都必须把 Hello Kuikly 跑起来二是理解“状态驱动 UI”这个核心心智模型三是知道页面之间怎么跳转。老师反复强调后面几天都会建立在这三件事上所以第一天的笔记一定要吃透。我个人的感受是目标定得务实没有一上来就追新概念而是先让你把一个能跑的程序放到设备上有了正反馈后面学起来才不慌。2. 环境准备从零搭好 Kuikly 开发环境2.1 DevEco Studio 安装与 SDK 配置先说个大前提电脑内存至少要 8G建议 16G。我第一次用 8G 内存的机器跑模拟器开完系统就剩不下多少余量编译一次要等半天。所以如果你手边的机器配置不高建议优先用真机调试模拟器可以放到后面再说。装 DevEco Studio 的过程和其他 IDE 差不多官网下载对应系统的安装包一路 Next。需要注意三点安装路径里不要有中文或空格否则后面找日志时很痛苦首次启动后会提示安装 HarmonyOS SDK这一步建议把 API 12 的版本装上如果网络不太好下载可能会中断尽量挑个闲时执行断点续传有时候并不靠谱重试几次不如直接重新下载。装上后要顺手验证一下环境变量。Windows 下确认hdc和hvigor是否在 PATH 里Mac/Linux 下就检查which hdc。这些工具在 SDK 的toolchains目录下如果 IDE 能正常同步一般会自动配好但命令行是否能直接用是另一回事。训练营里就有同学的 IDE 可以编译但命令行敲hdc list targets直接报 command not found折腾了十分钟。说到底环境问题八成都是“IDE 自己没问题但命令行工具链没接上”这一类。2.2 Kuikly CLI 的安装与工程初始化Kuikly 官方提供了一个命令行脚手架我用的命令是npm install -g kuikly/cli安装完成后用kuikly create helloKuikly初始化工程。这一步会询问项目名称、包名、选择模板。我选了默认的“基础模板”里面包含了最精简的单页面结构。如果后续要做 tab 栏或者列表页官方还有更多模板Day 1 先不贪多。初始化过程会拉取依赖时间长短取决于网络。跑完后目录里会多出helloKuikly文件夹里面结构大概长这样helloKuikly ├── AppScope │ ├── app.json5 │ └── resources ├── entry │ ├── build-profile.json5 │ ├── hvigorfile.ts │ └── src/main │ ├── module.json5 │ ├── ets │ │ ├── entryability │ │ │ └── EntryAbility.ets │ │ └── pages │ │ └── Index.ets │ └── resources └── oh-package.json5这个结构和 ArkUI 工程基本一致ets/pages目录装的是页面文件module.json5是模块配置EntryAbility.ets负责应用生命周期。Kuikly 在这一层做的额外封装主要在pages内部页面文件的核心长相会和 ArkUI 不太一样后面第 3 节会详细说。2.3 模拟器与真机调试准备调试前先把设备准备到位。模拟器方面DevEco Studio 自带 Device Manager可以在里面创建鸿蒙模拟器。需要注意模拟器镜像比较大首次下载要好几分钟而且对显卡和内存有要求启动后如果发现画面卡顿优先关掉系统的动画缩放把模拟器分辨率调低。真机方面需要一台鸿蒙手机在“设置-关于手机”连续点击版本号打开开发者模式然后在“开发者选项”里打开 USB 调试。插上电脑后用hdc list targets检查设备是否被识别能看到设备序列号就说明连接正常。这里有个 Day 1 最容易踩的坑很多人的笔电只有一个 Type-C 口插了手机就没办法接别的外设。建议带一个扩展坞否则后半天全在拔插线缆。真机调试时如果hdc list targets能识别但 IDE 同步应用时一直转圈大概率是手机弹窗“允许 USB 调试吗”没有点确认。这个弹窗偶尔会被系统信息遮住记得切到手机上看一眼。2.4 工程配置里需要提前检查的几项打开entry/src/main/module.json5重点检查两处一是deviceTypes数组里是否包含phone和tablet否则应用装不上对应设备二是abilities下的exported标记新建项目默认是true如果后面要联调别的模块这字段可能被 IDE 自动改成false导致拉起入口失败。Day 1 不需要深入理解所有字段但养成“看到配置先读一遍”的习惯会省很多事。另外oh-package.json5会记录项目依赖了哪些ohos或第三方的包。我在初始化后手动加了一个官方插件包结果版本号写错编译时报 dependency not found。教训是改版本号一定要去仓库确认再改不要凭记忆填。3. HelloKuikly跑通第一个页面3.1 入口文件与页面注册顺序工程创建好后默认打开的就是entry/src/main/ets/entryability/EntryAbility.ets这个文件负责应用的启动它内部会加载一个页面路径。我的模板里加载的是pages/Index。如果你想在启动时换到别的页面需要改这里。不过 Day 1 我们只要理解链路就够应用启动 - EntryAbility 拉起 - 找到对应页面组件 - 渲染到窗口。页面文件里Kuikly 推荐用Entry标记入口组件用Component标记普通组件。这个写法和 ArkUI 一致好处是如果以后要恢复用原生 ArkUI迁移成本不大。Index.ets 初始内容是个 Hello 页面我们直接清空重写这样更清楚每一行代码的作用。3.2 用组件拼出计数器页面我重写了Index.ets代码如下// Index.ets import { Column, Text, Button } from kuikly/core; Entry Component struct IndexPage { State count: number 0; build() { Column() { Text(Hello Kuikly) .fontSize(32) .fontWeight(FontWeight.Bold) .margin({ bottom: 24 }) Text(当前计数: this.count) .fontSize(20) .margin({ bottom: 12 }) Button(点我 1) .onClick(() { this.count; }) .width(120) .height(40) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }可能和你在网上看到的 ArkUI 例子很像因为 Kuikly 的组件本身就是 ArkUI 组件上的封装只是导入来源换成了kuikly/core。Column表示垂直布局容器里面依次放文本和按钮Text负责显示字符串Button绑定点击事件。State count声明一个状态变量初始值为 0点击按钮时加 1界面上的“当前计数”文本会自动刷新。跑起来后模拟器上会出现一个居中的页面点击按钮数字会增加。这个 Demo 虽然简单但它覆盖了今天最核心的两个概念声明式 UI 和状态驱动。第 4 节我会把这两个概念掰开讲。3.3 修改应用名和图标的基础操作跑通页面后老师让我们顺手改了一下应用显示名和图标为后面正式项目做准备。应用名在AppScope/app.json5里的label字段一般是资源引用的形式比如label: $string:app_name。对应的字符串值在resources/base/element/string.json里。改成你自己想用的名字重新编译桌面上的应用名就会变化。图标则要看resources/base/media目录下的icon.png直接把同尺寸的图片替换进去就行。鸿蒙对图标有前景层和背景层的要求但 Day 1 只是验证流程随便放一张 png 也能编过。唯一要注意的是图片命名必须保持为icon不能改成logo又忘记在配置里同步否则会编译失败。4. 核心概念声明式 UI 与状态驱动4.1 声明式 UI 到底怎么理解老一代界面开发比如命令行时代是命令式开发者一步一步告诉系统“先创建控件再设置属性再添加到父容器”每一步都是指令。声明式 UI 换了一种思路开发者只描述“界面应该长什么样”至于怎么创建、怎么更新都交给框架。你可以把它理解成点和菜的关系命令式是自己去后厨盯着“先洗菜、再切菜、最后下锅”声明式是在菜单上勾几道菜后厨自然会按流程做出来。你只需关心“菜单”上的变化不用关心后厨具体怎么颠勺。在 Kuikly 里build()方法就是这张“菜单”。每次状态发生改变框架会重新执行build()中描述的结构和旧的 UI 做对比只更新需要变化的部分。第一次接触这个概念会觉得有点抽象但多写几个页面就适应了。我自己的转化方法是把所有界面都想象成一棵由Column、Row、Text、Button等基础组件组成的树build()就是负责把这棵树描述出来。4.2 状态驱动数据是 UI 的唯一真源配合声明式 UI 的还有另一个核心机制状态驱动。你在组件里定义的State变量会被框架记录为“依赖”。当变量的值变化时所有使用这个变量的 UI 节点都会自动重新渲染你不用手动调用刷新方法。这就是“数据是唯一真源”的意思界面永远跟着数据走。训练营老师用了一个很形象的比喻UI 就像水面数据像扔进水里的石头石头一动水花自然就荡开不需要有人拿着棍子去搅。我们那个计数器 Demo 就是最好的例子唯一的状态是count按钮的点击改的是count界面里两处用到count的文本会自动跟着变。如果换成老式命令式写法你至少要在回调里手动设置Text.setText()写多了就容易漏。有一点需要留意State只适合管理“组件自己内部”的临时状态。如果多个页面要共享同一份数据Day 1 用的简单工程肯定不够后面会引出Prop、Link、全局状态管理等话题。今天只需要记住“子组件不要直接改父组件的State变量”这个原则避免埋雷。4.3 从计数器到多状态小练习下午的练习环节老师让大家给计数器加一个重置按钮和减一按钮。我顺手把代码改成下面这样Button(减一) .onClick(() { if (this.count 0) { this.count--; } }) .width(80) .height(40) Button(重置) .onClick(() { this.count 0; }) .width(80) .height(40)逻辑本身很简单但练习的目的在于让你体会“改状态而不是改 UI”这个原则。我一开始写重置函数时忍不住想直接去改Text的内容后来才意识到完全不需要。减一的时候我加了个条件判断防止计数变成负数。这种小逻辑在状态驱动模式下也很直观把条件判断写在状态更新的地方界面不需要做任何反应。5. 路由跳转从单页到多页5.1 注册第二个页面并配置路由一个应用不可能只有一个页面Day 1 最后讲了怎么跳转到第二个页面。Kuikly 的路由底层还是鸿蒙的router但提供了更简洁的封装。首先要在pages目录下新建一个SecondPage.ets内容先写个简单的文本// SecondPage.ets import { Column, Text } from kuikly/core; Entry Component struct SecondPage { build() { Column() { Text(这是第二个页面) .fontSize(24) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }然后回到第一个页面在按钮的点击事件里调用路由方法。Kuikly 暴露了一个Router对象用一行代码完成跳转import { Router } from kuikly/core; // 在某个按钮的回调里 Router.pushUrl({ url: pages/SecondPage });注意这里的url要写页面相对路径不能带.ets后缀。如果跳转时报错找不到页面多半是路径写错了或者页面没有被模块识别。检查点有两个一是页面文件确实在ets/pages目录下二是看module.json5里是否声明了相关路由能力。用小项目踩一遍这些坑印象会特别深。5.2 页面间传参与返回值处理跳转通常不是单向的第二个页面也可能要把数据带回第一个页面。Kuikly 支持通过params传一个对象过去Router.pushUrl({ url: pages/SecondPage, params: { from: IndexPage, topic: Day1 } });在第二个页面里可以用Router.getParams()拿到这个对象const params Router.getParams() as Recordstring, string; if (params) { console.info(来自 ${params.from}主题 ${params.topic}); }这里有个小细节params的键值类型在纯 ArkTS 环境下不能随便写成Object最好用具体的接口类型或Recordstring, string强转否则类型检查会警告。返回时如果想要回传数据可以在第二个页面调用Router.back()前把数据放到params里再返回。不过这一块细节偏多Day 1 只是给了个引子后续课程应该会深入。先知道“可以传参、可以返回”就够了至少做基础的多页演示不会卡壳。5.3 页面生命周期钩子一览虽然第一天没有展开讲生命周期但老师在一张 PPT 里列了常用钩子我趁热记了下来。主要有onPageShow、onPageHide、onBackPress这几个。onPageShow在页面每次显示时触发适合做一些数据刷新onPageHide在页面被切走时触发onBackPress在系统返回键被按下时触发你可以在里面拦截返回操作比如弹一个确认框。我在 Demo 里试着在SecondPage里加了onPageShow打一行日志确认触发时机发现每次从第一个页面跳过去都会打印一次但从二级页面返回一级页面时不会触发二级页面的onPageShow。这个行为符合预期但初学容易搞混最好自己动手验证一遍。6. Day 1 我踩过的几个大坑6.1 模拟器启动失败端口被占用下午开场我正在启动模拟器结果 Device Manager 里提示启动失败。查了日志才知道是端口冲突之前不小心开过一个后台进程占用了模拟器要用的端口。解决办法不复杂在命令行执行hdc kill把所有相关进程退掉然后重启模拟器。如果还不行就用系统工具看端口占用情况。Windows 可以用netstat -ano | findstr 端口号Mac/Linux 用lsof -i :端口号找到 PID 后手动结束进程。这个坑其实挺好防模拟器在跑的时候不要频繁插拔设备如果中途 HDC 服务卡死优先试试hdc kill而不是直接重启电脑。6.2 编译报错undefined: Text有同学第一次跑工程时报undefined: Text原因非常简单就是代码里用了Text但顶部导入语句里没有从kuikly/core导入Text。ArkTS 的语法检查很严格编译器发现未定义的标识符会直接中断。解决方案就是补上导入import { Column, Text, Button, Router } from kuikly/core;另外还要注意组件名的首字母大写。text和Text在 ArkTS 里是两个不同的东西前者可能被当成变量处理报的错会让你摸不着头脑。建议每次写完代码先看一眼导入再考虑排错。6.3 真机同步后页面没变化真机调试时还有一个让人抓狂的现象改了几行代码点运行手机上还是旧界面。先排查是否构建缓存没清干净。可以删掉工程目录下的build、.cxx等临时文件夹重新编译。如果依然不行检查手机上是不是原来装的应用没有卸载干净。鸿蒙应用升级安装时如果签名发生变化系统不会直接覆盖会拒绝安装或保留旧版本。我的建议是真机调试时保持单一签名配置不要反复切换调试证书。训练营为了方便给我们配了一个测试证书但它有有效期到了节点需要重新生成。如果遇到安装失败且日志里出现 signature 相关的关键词基本都是证书没配对。6.4 命令行工具找不到的应急方案前面提到过hdc命令找不到的问题。如果 IDE 能用但命令行不行可以直接用 SDK 路径下的完整工具。在 DevEco Studio 的安装目录里搜索hdc.exe或hdc然后把它加到系统的 PATH 里。Mac 上通常是/Users/你的用户名/Library/Huawei/Sdk/.../toolchains/hdc。加上后重开终端再敲hdc list targets就能识别设备了。还有一个小技巧如果临时不想改 PATH可以直接在 IDE 的 Terminal 面板里运行命令那个面板通常已经帮你配置好环境变量能省不少事。6.5 报错信息速查表一天的实操下来我把遇到的报错整理成了一张表后面几天应该还会继续往里面加报错关键词常见原因处理方式undefined: Text组件未导入从kuikly/core补导入Cannot find module依赖缺失或版本错误检查oh-package.json5重新安装device not foundUSB 未插好 / HDC 端口占用重插执行hdc killsignature error调试证书不匹配检查真机调试签名配置url not registered路由路径拼写错误检查pages目录和 url 前缀这张表的作用不是让你死记硬背而是帮你快速定位方向。编译器给出的错误信息通常已经指出了关键词你要做的就是顺着关键词去查对应的配置或导入很多时候十分钟就能解决的问题却因为“看不懂英文”而拖了半天。7. 第一天结束后的几点体会Day 1 结束后我自己把练习又敲了两遍。第一遍看着官方示例抄第二遍关掉文档从零开始写发现还是有几个地方记不牢比如路由的url路径要不要加.ets又比如导入kuikly/core时漏了Router导致的编译报错。多看报错信息比反复猜更有效ArkTS 的错误提示其实挺清晰只是英文加代码行号需要点耐心。下一步我打算把 Day 2 预习一下做一个列表页用List和ForEach展示数据再把状态管理从State扩展到Prop、Link这类父子组件通信的场景。另外群里有同学提到可以用 Kuikly 做跨端的思路把同一套页面逻辑复用到其他平台我准备等基础更牢以后再尝试。第一天说到底就是搭骨架真正的麻烦还在后面把路走稳比走得快更重要。
阅读完成 · 觉得有帮助?
咨询建站