#HarmonyOS NEXT体验官# HarmonyOS UI可预览架构大结局(上) 原创
前言
半年前我写过两篇帖子,HarmonyOS UI可预览架构探索 和 HarmonyOS UI可预览架构探索(续) 。当时的背景是基于api9。最近一个偶然的机会,发现Dev Eco Studio支持previewer的数据模拟了,我惺忪的睡眼蹭的就亮了,突然就不困了啊。这不就是我之前一直想要的preview和真实运行数据分离嘛。这回IDE原生支持了。我又看了一眼支持的历史,是从api11之后开始的,那之前api9的时候确实得自己折腾一个架构出来。话不多说,搞起来。
开发环境:
Windows 11
DevEco Studio NEXT Developer Beta2
Build Version: 5.0.3.500, built on July 17, 2024
运行环境:
模拟器
HarmonyOS NEXT Developer Beta2
参考文档:
添加依赖
在工程下方的终端窗口中输入命令
cd entry
ohpm install @ohos/hamock
或者在oh-package.json5
中手动添加依赖
"devDependencies": {
"@ohos/hamock": "1.0.0"
}
UI组件上的Mock
Hamock提供了@MockSetup
用于修饰Mock方法,仅支持声明式范式的组件。当开发者预览该组件时,预览运行时将在组件初始化时执行被@MockSetup修饰的方法。因此,开发者可以在这个被修饰的方法内重定义组件的方法或重赋值组件的属性,其将在预览时生效。
@MockSetup
修饰的方法仅在预览场景会自动触发,并先于组件的aboutToAppear执行。
如果写了多个以@MockSetup
修饰的方法,只会执行第一个声明的方法,之后声明的方法都被忽略。
-
创建一个界面
Index
import { router } from '@kit.ArkUI' @Entry @Component struct Index { @State title: string = "title" setup() { return "setup" } build() { Column() { Text(this.title) .fontSize(50) .id("title") .onClick(() => { router.pushUrl({ url: "pages/SecondPage", }) }) } .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) .height('100%') .width("100%") .backgroundColor("#DCDCDC") .padding({ top: 10, bottom: 10 }) } }
模拟器和预览器的截图对比,现在为止两边是一样的。
-
在ArkTS页面代码中引入Hamock。
import { MockKit, when, MockSetup } from '@ohos/hamock';
-
在Index中定义一个方法
mockTitle()
,并用@MockSetup修饰该方法,这个方法名可以随意取,并且不需要传入参数。@MockSetup mockTitle() { this.title = "title mock" }
现在看下效果,立竿见影。预览窗的Text控件直接显示了"title mock"。说明预览窗执行了
mockTitle()
方法,但运行工程的的话,没有执行该方法。
-
如果在
aboutToAppear()
中如果对title属性有修改,那么运行和预览都会统一变成aboutToAppear()
中修改的值。因为预览@MockSetup
执行完之后会执行aboutToAppear()
,运行也会直接执行aboutToAppear()
。aboutToAppear(): void { this.title = "aboutToAppear" }
-
除了直接改属性值,还能mock方法返回值。创建一个新方法
setup()
,返回字符串"setup"。setup() { return "setup" }
在
aboutToAppear()
中用setup()的返回值设置title的值aboutToAppear(): void { this.title = this.setup() }
在
@MockSetup
中按如下代码编写。this.title = "title mock"
继续保留,可以观察出来代码的执行顺序。然后创建一个MockKit
实例,调用mocker.mockFunc()
来绑定需要mock的方法。最后调用when()
来配置mock的入参和出参。这一步我们先学习如何mock函数返回值。在afterReturn()
中传入mock的返回值@MockSetup mockTitle() { this.title = "title mock" const mocker: MockKit = new MockKit(); const mockfunc: Object = mocker.mockFunc(this, this.setup); // mock 指定的方法在指定入参的返回值 when(mockfunc)().afterReturn("setup mock") }
-
现在预览器的执行顺序是,
@MockSetup
中修改了title值,并mock了setup()
函数的返回值。之后代码走到aboutToAppear()
,title又被修改。此处如果是运行的状态,
setup()
返回字符串"setup",如果是预览器,则setup()
的返回值被mock成了"setup mock"。 -
如果
setup()
接受参数,则配置mock的时候需要指定入参的内容,只有入参匹配上,mock才会生效。修改
setup()
和aboutToAppear()
方法setup(value: string) { return value } aboutToAppear(): void { this.title = this.setup("aboutToAppear") }
根据修改后的
setup()
入参,@MockSetup
应该这样修改@MockSetup mockTitle() { this.title = "title mock" const mocker: MockKit = new MockKit(); const mockfunc: Object = mocker.mockFunc(this, this.setup); // mock 指定的方法在指定入参的返回值 when(mockfunc)("aboutToAppear").afterReturn("aboutToAppear mock") }
此时mock生效
如果随意配置入参,或者不填写入参,会无法渲染界面。
下集预告
下一篇中,将介绍系统模块,依赖模块和本地模块的mock。