概述
快应用类似于微信小程序,但它的框架已被集成到手机操作系统中,你不需要再安装额外的 App。
快应用开发标准,由国内安卓手机厂商大佬们制定,但只要你拥有前端技术的开发能力,就能够很快上手。
快应用具备如下特点:
- 功能完备
- 原生应用体验
- 易于留存
- 即点即用
- 互联互通
- 无版本碎片
基本概念
基础目录结构
├── sign rpk 包签名模块
├── src
│ ├── Common 公用组件
│ ├── Home 页面目录
│ | └── index.ux 页面文件
│ ├── app.ux APP 文件,可引入公共脚本,暴露公共数据和方法等
│ └── manifest.json 项目配置文件
└── package.json
manifest.json
在配置文件中,你需要配置应用包名、版本信息、以及页面 UI 的显示样式等。
此外,所有用到的框架接口你需要在 features
字段中显式声明,否则会报错:
{
"features": [{ "name": "system.fetch" }]
}
应用中用到的页面路由,也需要在配置文件中配置好:
{
"router": {
"entry": "Home",
"pages": {
"Home": {
"component": "index"
},
"Detail": {
"component": "index"
}
}
}
}
应用入口: app.ux
在入口文件 app.ux
中有 2 个生命周期方法:onCreate
、onDestroy
。
你也可以定义或从模块中导入些方法,然后暴露到全局进行共享,在页面中通过 this.$app.$def
调用,比如:
// app.ux
import { method1, method2 } from 'someUtils';
export default {
method1,
method2
};
// home.ux
export default {
onShow() {
this.$app.$def.method1();
}
};
如果调用的方法,会用到 app
实例中的属性,那么你只能使用 this.$app
来调用:
// app.ux
export default {
onCreate() {
this.name = 'Nicolas';
},
method3() {
return this.name;
}
};
// home.ux
export default {
onShow() {
this.$app.method3();
}
};
此外,项目中频繁用到的框架接口,也可以在入口文件中导入并暴露到全局:
// app.ux
import device from '@system.device';
export default {
async getDeviceInfo() {
try {
const { data } = await device.getInfo();
return data;
} catch (err) {
// error
}
},
};
// home.ux
export default {
onShow() {
this.$app.$def.getDeviceInfo().then((data) => {
this.deviceInfo = data;
});
}
};
页面组件
类似于 Vue 和微信小程序,快应用的页面组件 page.ux
文件也分 3 个部分:template
、script
和 style
。
模板
template
中除了事件方法的调用 @event-name="handleEventName"
,其他一律用模板语法 {{}} 来解析 ViewModel
中的数据,包括:框架指令。
另外,文本内容只能出现在特定的组件中,比如: text
、span
等。
数据模型
页面数据模型的声明分为 3 种:public
,protected
和 private
。
数据模型的声明类型,影响到页面之间传递数据的覆盖机制。public
和 protected
声明的数据可以被覆盖,只是,protected
只能被内部覆盖,比如:router
,而 public
可以被外部覆盖,比如:Deeplink。
生命周期
页面组件包括如下声明周期:
onInit
:ViewModel
的数据已可以使用,只执行一次onReady
:可以获取DOM
节点,只执行一次onShow
:每次显示都执行,比如:从后台进程重新唤起,或从另一个页面返回onHide
:每次隐藏都执行,比如:隐藏到后台进程、打开另一个页面等onDestroy
:页面销毁时执行,如果这里包含了异步执行的逻辑,可能不会执行onBackPress
:返回true
后可阻止返回(包括物理键和左上角返回键),需要手动执行返回逻辑,比如:router.back()
onMenuPress
样式和布局
页面样式统一使用 border-box
盒模型,和 flex
布局。你不需要额外声明。
单位长度使用 px
,页面设计稿的尺寸可在 manifest.json
中配置(默认 750),然后设计稿中标识的像素尺寸值可直接使用,框架会自动进行移动端屏幕适配。
比如,设计稿为 1080 宽:
{
"config": {
"designWidth": 1080
}
}
安装 NPM 的 less-loader
后,可以让 style
支持 less
预处理器的语法:
npm i --save-dev less less-loader
<style lang="less">
font-size
和 color
等很多属性,没有继承的概念,只能在 text
等包含文本的组件中一一声明。
而且,大部分浏览器端的样式,框架中并不支持,写法和用法也有很多区别(比如背景色只能用 background-color
,不支持简写)。
你也可以继续踩坑,然后和我一起探讨下。
自定义组件
声明组件
组件文件建议放到 /Common/
目录下。
组件文件的结构类似于页面文件,但数据模型只能通过 props
传入,或者定义在 data
中。
你也可以监听传入 props
属性的变化:
export default {
props: ['value'],
onInit() {
this.$watch('value', 'handleValueChange')
}
};
生命周期也比较有限,只有:onInit
、onReady
和 onDestroy
。
如果自定义组件需要感知页面的显示和隐藏等生命周期,可以通过事件传播来处理,比如:
// page.ux
{
onShow() {
this.$broadcast('pageShow');
}
}
// component.ux
{
onInit() {
this.$on('pageShow', this.handlePageShow);
}
}
组件中引用的资源(比如:图片等),需要使用绝对路径来引用,否则组件被页面导入后,资源可能会加载失败:
<image src="/Common/Loading/images/icon.png"></image>
使用组件
在页面,或者其他组件中导入即可,import
中的 name
属性即为组件使用时的名称。
<import name="loading" src="../Common/Loading"></import>
<template>
<div>
<loading text="Loading..."></loading>
</div>
</template>
事件
原生组件和页面的事件
原生组件的事件类似于浏览器中的 DOM
,自带了很多通用事件,比如:click
,foucs
等,在模板中需要加 @
或 on
前缀。
页面自定义事件,可以在 onInit
中注册,然后进行手动触发:
export default {
onInit() {
this.$on('customEventType', this.handleCustomEvent)
},
handleCustomEvent({ detail }) {
// detail 为触发事件时传入的数据参数
},
onShow() {
this.$emit('customEventType', {
// event detail data
});
}
}
自定义组件的事件
注册自定义组件的事件有 2 种方式:
- 模板中的组件节点
- 页面的
onInit
中用this.$on
在模板中注册事件时,类似于原生组件,需要加 @
或者 on
前缀。在组件内部,通过 this.$dispatch
向上传播,上面注册的 2 种方式都可以被触发。类似于页面中的自定义事件:
// page.ux
<import name="profile" src="../Common/Profile"></import>
<template>
<div>
<profile @name-change="handleProfileNameChange"></profile>
</div>
</template>
// profile.ux
export default {
handleNameChange() {
this.$dispatch('nameChange', { name: this.name });
}
};
事件还可以向下传播,比如从页面触发自定义组件的事件,就像前面讲到的:pageShow
,参考本篇文章的自定义组件一节。
创建项目
首先,你可以有 2 种方式来创建快应用项目:
- 快应用开发工具
- 命令行
快应用开发工具
用官方的快应用开发工具(IDE)来创建项目比较简单,可以参考如下步骤:
- 下载并安装 IDE
- 打开后,点击左侧的“+”号图标按钮
- 进入项目创建界面
- 输入:项目路径、项目名称、应用名称和应用包名等信息
- 稍等片刻后,会并自动打开新建的快应用工程
命令行
确保你的 NodeJS 版本是 8.0+ 的,推荐 10.0+,更快、更好、更稳定……
然后,你需要:
1、全局安装快应用命令行工具:
npm i -g hap-toolkit
2、用 hap
命令来创建一个项目模板:
hap init awesome-quick-app
3、安装 NPM 依赖:
npm i
开发与调试
推荐采用 VSCode(开发) + 快应用开发工具(调试),双剑合璧。
开发
推荐安装 VSCode 对 *.ux
文件的语法高亮插件: QuickApp for Highlighter
,当然,你也可以选择官方的 Hap Extension
。但个人在使用中,发现 Hap Extension
会导致 VSCode 频频卡死的现象,当然你也可以亲自尝试下。
其实,官方 IDE 也不错,但由于个人喜好,感觉 VSCode 更专业点,当然你可以自由选择。
调试
快应用得通过真机来调试。
调试前,请务必开启 manifest.json
中的日志输出配置:
"config": {
"logLevel": "debug"
},
如果手机与电脑处于不同局域网内,需要开启快应用调试器的开启 USB 调试开关。
自动模式
推荐使用快应用开发工具进行调试,你只需点击 IDE 左侧的“三角形”图标按钮,然后以下步骤会自动进行:
- 检测并安装手机的:快应用预览版、快应用调试器、快应用调试内核
- 开启调试服务器和代码更新,自动推送安装新的
rpk
包 - 打开电脑端的调试窗口
- 打开手机端的快应用
如果电脑端的调试窗口没有打开,你可以尝试点击 IDE 顶部的“刷新”图标按钮进行重试。
手动模式
当然,如果你想要自由掌控,你也可以手动执行以上步骤来开启调试。
2、开启调试服务器:
npm run server
3、自动编译项目并更新应用:
npm run watch
4、打开手机端的快应用调试器,扫码安装(同网),或者 USB 调试(非同网)
5、然后,点击开始调试按钮
由于我是懒人,我还是比较倾向自动调试模式!
测试与发布
测试
进入测试流程后,测试机同样需要安装:快应用调试器和快应用预览版。
然后执行如下命令来打一个测试包:
npm run build
测试包输出路径位于:dist/<package>.debug.rpk
。
测试同学需要手动安装这个 rpk
包,通过快应用调试器的“本地安装”来进行。
发布
如果你是第一次发布,你需要一个 release 签名证书,可以通过如下方式生成:
- 打开开应用开发工具(IDE)
- 点击左侧的“纸飞机”图标按钮,然后打开一个创建签名的窗口
- 输入相关信息
- 点击“完成”按钮,生成 release 签名
- 接着会自动生成发布用的
rpk
包
release 包的输出路径和测试包相同,文件输出后缀为 *.release.rpk
。
如果你是第二次发布,直接执行如下命令即可生成发布包:
npm run release
注意:在生成发布包前,需要更新 manifest.json
的 2 个字段:versionName
和 versionCode
,versionName
更新规则可参考: semver。versionCode
字段在每次 release 时需要自增加 1。
hap
命令行工具好像并没有提供升级版本号的功能,但你可以用 shell
自己写一个,比如:
sed -i '' "s/\(\"versionName\": *\).*/\1\"1.0.1\"/"
当然,上面代码中的 1.0.1
是需要写个逻辑来自动更新的,类似于 npm version
命令。
参考文档
- 快应用技术开发文档,快应用联盟