摘要:注册账号首先你需要一个手机厂商对应开发者账号和快应用账号由于博主的手机是华为,就在华为官网注册一个个人开发者账号就好啦,这个部分就不具体展开了。
博主的开发及调试环境是 macOS 10.13.4 + Chrome/65.0.3325.181 + honorV9 EMUI8.0.0(Android8.0.0)注册账号本文适合有一定前端开发经验的小伙伴(有一定经验看原文档太累赘了,而且环境配置部分原文写的太零碎了),最后总结了一些开发过程中遇到的坑。附文档链接:https://doc.quickapp.cn/
本文没有提到的部分和正常前端开发保持一致,也可能是我还没有遇到的坑。。。
首先你需要一个手机厂商对应开发者账号和快应用账号
由于博主的手机是华为,就在华为官网注册一个个人开发者账号就好啦,这个部分就不具体展开了。相关地址快应用也给我提供了一份列表和指南。值得说明的是,这个账号是需要实名制的,有上传身份证照片和个人照片审核的,审核需要1-2个工作日(华为使用芝麻信用认证可以即即刻生效,不知道其他厂家什么情况)。
然后打开快应用官网 https://www.quickapp.cn/, 点击右上角的注册,注册一个快应用账号,这个部分很简单,也不展开了。
登陆以后我们可以看到导航栏上多出来一个开发者中心标签,点击进去,选择【厂商账号绑定】选项卡,选择你的手机品牌方标签进行绑定即可,目前小米、华为、金立、魅族、努比亚、OPPO 和 VIVO 都已经可以绑定了,而中兴、联想和一加还不能绑定。该绑定过程同样需要1-2个工作日审核。
首先你需要安装 node v6.11.3 这是快应用官方推荐的版本
注意:不要使用 v8.0.* 这个版本内部 ZipStream 实现与 node-archive 包不兼容,会引起报错
如果你已经使用了 node 高版本,可以安装 nvm 管理 node 版本(如果你是第一次安装 node 可以直接安装 v6 版本,跳过该步骤)。
安装nvm, 注意不要使用 brew 安装,因为 curl 安装不需要手动配置 .bashrc :
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash
然后安装对应版本node:
nvm install v6.11.3
检查当前使用 node 版本:
nvm current
此时应该已经是我们需要的版本了,如果不是,可以手动切换。查看已安装的 node 版本,和切换到已安装的版本:
nvm ls # 查看已安装版本 nvm use v6.11.3 # 使用已安装版本
更多 nvm 用法直接输入:
nvm --help
到这里,我们继续快应用开发,全局安装脚手架:
npm install -g hap-toolkit
检测是否安装成功:
hap -V调试工具
chrome 的 devTools 肯定是必不可少的。除此之外我们需要在手机安装一下两个应用:快应用调试器(左),快应用预览平台(右)
如果你不安装【快应用预览平台】,那么【快应用调试器】中的按钮都是不可点击的。而【快应用预览平台】里面其实啥也看不到,就是一个供快应用工作的壳。完整安装好以后【快应用调试器】如下图。
当然官方也给了一份 源码, 方便大家熟悉生命周期,样式,自定义组件,事件传递,组件使用。注意:下载后请记得操作:hap update --force,增加编译支持。
最后 adb 安装(Homebrew):
brew cask install android-platform-tools
检测是否安装成功:
adb devicesDemo 项目生成
我们利用脚手架新建一个项目, 并且进入该项目, init 过程中需要输入项目名称:
hap init demo && cd demo
注意:之后的所有操作都在这个目录下面
这是 demo 目录结构
├── sign #rpk包签名模块 │ └── debug #调试环境 │ ├── certificate.pem #证书文件 │ └── private.pem #私钥文件 ├── src │ ├── Common #公用的资源和组件文件 │ │ └── logo.png #应用图标 │ ├── Demo #页面目录 │ | └── index.ux #页面文件,可自定义页面名称 │ ├── app.ux #APP文件,可引入公共脚本,暴露公共数据和方法等 │ └── manifest.json #项目配置文件,配置应用图标、页面路由等 └── package.json #定义项目需要的各种模块及配置信息
需要注意的是,sign 用来存放签名模块,sign/debug 中有用于调试的证书的私钥,但debug签名由于是公开的,安全性无法保证。在 release 发布之前一定要添加 release 目录并且写入对应的证书和私钥:
openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 3650 -out certificate.pem mkdir sign/release && mv *.pem ./sign/release/
安装相关依赖:
npm install
如果上面的安装很慢,可以使用淘宝的资源:
npm install --registry=https://registry.npm.taobao.org
脚手架已经提供很多运行方式:
npm run release # 发布程序包,在 /dist/.signed.rpk,注意需要使用 release 签名模块 npm run build # 生成 build 和 dist 两个目录。前者是临时产出,后者是最终产出 npm run watch # 文件保存时自动编译和调试调试方法
项目已和产生了 rpk 包,在做好之前的准备工作已后,运行:
npm run server # 当然,你可以通过 --port XXXX 指定端口,默认12306
此时,会在控制台和 http://localhost:12306 得到一个二维码,利用【快应用调试器】中的扫码安装,即可在手机上看到效果了。
此时你退出预览界面,点击【快应用调试器】中的开始调试,会同步在 chrome Devtool 中打开调试窗口,原理同在 chrome://inspect 中使用的远程调试功能,如下图:
调试可以采用一下三种方式:
npm run build # 手动编译 + 手动刷新 npm run build && npm run notify # 手动编译 + 自动刷新 npm run watch # 自动编译 + 自动刷新
注意:使用远程调试请确保手机与PC在同一局域网
开发
IDE / Code Editor
VS Code: 搜索 Hap Extension 安装插件即可
webStorm: 可以通过 html 关联 ".ux" 文件
sublime: 选择 html 高亮即可
Android Studio: 使用 Android Monitor 看 console
console
为了正常使用 console.log 修改 src/manifest.json 中的 config 如下:
{ "config": { "logLevel": "debug" } }
console 仅支持 info, log, warn, error, debug 方法。
LESS 支持
安装 less、less-loader
在 style 标签上添加 lang="less" 属性即可
Async Function 支持
安装 babel-runtime
将 babel 注入项目全局
/* app.ux 文件(如果没有自己在 Common 里建一个)*/目录结构 与 manifest 目录结构
根目录下的 sign 文件上文已经提到过,其他文件目录不再赘述,因为前端项目大多如此,这里仅仅说 src 目录:
src ├── manifest.json # 配置文件 ├── app.ux # 入口文件 ├── Page1 # 页面1 │ ├── page1.ux ├── Page2 # 页面2 │ ├── page2.ux └── Common # 公共页面和资源 ├── ComponentA.ux ├── ComponentB.ux └── xxx.pngmanifest
manifest
属性 | 类型 | 默认值 | 必填 | 描述 |
---|---|---|---|---|
package | String | - | 是 | 应用包名,确认与原生应用的包名不一致,推荐采用com.company.module的格式,如:com.example.demo |
name | String | - | 是 | 应用名称,6个汉字以内,与应用商店保存的名称一致,用于在桌面图标、弹窗等处显示应用名称 |
icon | String | - | 是 | 应用图标,提供192x192大小的即可 |
versionName | String | - | 否 | 应用版本名称,如:"1.0" |
versionCode | Integer | - | 是 | 应用版本号,从1自增,推荐每次重新上传包时versionCode+1 |
minPlatformVersion | Integer | - | 否 | 支持的最小平台版本号,兼容性检查,避免上线后在低版本平台运行并导致不兼容;如果不填按照内测版本处理 |
features | Array | - | 否 | 接口列表,绝大部分接口都需要在这里声明,否则不能调用,详见每个接口的文档说明 |
config | Object | - | 是 | 系统配置信息,详见下面说明 |
router | Object | - | 是 | 路由信息,详见下面说明 |
display | Object | - | 否 | UI显示相关配置,详见下面说明 |
config
用于定义系统配置和全局数据。
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
logLevel | String | log | 打印日志等级,分为off,error,warn,info,log,debug |
designWidth | Integer | 750 | 页面设计基准宽度,根据实际设备宽度来缩放元素大小 |
data | Object | - | 全局数据对象,属性名不能以$或_开头,在页面中可通过this进行访问;如果全局数据属性与页面的数据属性重名,则页面初始化时,全局数据会覆盖页面中对应的属性值 |
router
用于定义页面的组成和相关配置信息,如果页面没有配置路由信息,则在编译打包时跳过。
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
entry | String | - | 首页名称 |
pages | Object | - | 页面配置列表,key值为页面名称(对应页面目录名,例如Hello对应"Hello"目录),value为页面详细配置page,详见下面说明 |
router.page
用于定义单个页面路由信息。
属性 | 类型 | 默认值 | 必填 | 描述 |
---|---|---|---|---|
component | String | - | 是 | 页面对应的组件名,与ux文件名保持一致,例如"hello" 对应 "hello.ux" |
path | String | /<页面名称> | 否 | 页面路径,例如“/user”,不填则默认为/<页面名称>。path必须唯一,不能和其他page的path相同。下面page的path因为缺失,会被设置为“/Index”:"Index": {"component": "index"} |
filter | Object | - | 否 | 声明页面可以处理某种请求 |
router.page.filter
声明页面可以处理某种请求,页面可以从$page获取打开页面的参数。filter的结构如下:
"filter": { "": { "uri": " " } }
属性 | 类型 | 默认值 | 必填 | 描述 |
---|---|---|---|---|
action | String | - | 是 | 请求的动作,目前仅支持view这一种 |
uri | Pattern | - | 是 | 请求的数据的匹配规则。必须是正则表达式。如https?://.*可以匹配所有http和https类型的网址。 |
display
用于定义与UI显示相关的配置。
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
backgroundColor | String | #ffffff | 窗口背景颜色 |
fullScreen | Boolean | false | 是否是全屏模式,默认不会同时作用于titleBar,titleBar需要继续通过titleBar控制 |
titleBar | Boolean | true | 是否显示titleBar |
titleBarBackgroundColor | String | - | 标题栏背景色 |
titleBarTextColor | String | - | 标题栏文字颜色 |
titleBarText | String | - | 标题栏文字(也可通过页面跳转传递参数(titleBarText)设置) |
menu | Boolean | false | 是否显示标题栏右上角菜单按钮 |
pages | Object | - | 各个页面的显示样式,key为页面名(与路由中的页面名保持一致),value为窗口显示样式,页面样式覆盖default样式。 |
开发基础 保留字{{title}} ? {{($item || {}).name}} {{($item || {}).value}} ![]()
![]()
This is children of hint templete.
除了传统保留字,添加了 show tid 等;
生命周期页面生命周期
属性 | 类型 | 参数 | 返回值 | 描述 | 触发时机 |
---|---|---|---|---|---|
onInit | Function | 无 | 无 | 监听页面初始化 | 当页面完成初始化时调用,只触发一次 |
onReady | Function | 无 | 无 | 监听页面创建完成 | 当页面完成创建可以显示时触发,只触发一次 |
onShow | Function | 无 | 无 | 监听页面显示 | 当进入页面时触发 |
onHide | Function | 无 | 无 | 监听页面隐藏 | 当页面跳转离开时触发 |
onDestroy | Function | 无 | 无 | 监听页面退出 | 当页面跳转离开(不进入导航栈)时触发 |
onBackPress | Function | 无 | Boolean | 监听返回按钮动作 | 当用户点击返回按钮时触发。返回true表示页面自己处理返回逻辑,返回false表示使用默认的返回逻辑,不返回值会作为false处理 |
onMenuPress | Function | 无 | 无 | 监听菜单按钮动作 | 当用户点击菜单按钮时触发 |
A页面的生命周期接口的调用顺序:
打开页面A:onInit() -> onReady() -> onShow()
在页面A打开页面B:onHide()
从页面B返回页面A:onShow()
A页面返回:onBackPress() -> onHide() -> onDestroy()
应用生命周期
属性 | 类型 | 参数 | 返回值 | 描述 | 触发时机 |
---|---|---|---|---|---|
onCreate | Function | 无 | 无 | 监听应用创建 | 当应用创建时调用 |
onDestroy | Function | 无 | 无 | 监听应用销毁 | 当应用销毁时触发 |
全局对象 (通过 this 访问)
的属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$app | Object | - | 应用对象 |
$app.$def | Object | - | 获取在app.ux中暴露的对象 |
$app.$data | Object | - | 获取在manifest.json的config.data中声明的全局数据 |
$page | Object | - | 页面对象 |
$page.action | String | - | 获取打开当前页面的action。仅在当前页面是通过filter匹配的方式打开时有效,否则为undefined。参见manifest |
$page.uri | String | - | 获取打开当前页面的uri。仅在当前页面是通过filter匹配的方式打开时有效,否则为undefined。参见manifest |
$page.setTitleBar | Function | Object* | - |
$valid | Boolean | - | 页面对象是否有效 |
$visible | Boolean | - | 页面是否处于用户可见状态 |
* this.$page.setTitleBar 参数属性包括:
{ text: "Hello QuickApp", //标题栏文字 textColor: "#ffff", //文字颜色 backgroundColor: "#434343", //背景颜色 backgroundOpacity: "0.8", //背景透明度 menu: false, //是否在标题栏右上角显示菜单按钮 | 设置当前 }
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$element | Function | id: String | 获取指定id的组件dom对象,如果没有指定id,则返回根组件dom对象用法:this.$element("xxx")获取id为xxx的组件实例对象 this.$element() 获取根组件实例对象 |
$root | Function | 无 | 获取顶层ViewModel |
$parent | Function | 无 | 获取父亲ViewModel |
$child | Function | id: String | 获取指定id的自定义组件的ViewModel用法:this.$child("xxx") 获取id为xxx的div组件ViewModel |
$vm deprecated | Function | id: String | 请使用上面this.$child("xxx")替代 |
$rootElement deprecated | Function | 无 | 请使用上面this.$element()替代 |
$forceUpdate | Function | 无 | 强制页面刷新 |
公共属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$set | Function | key: String value: Any |
添加数据属性,必须在onInit函数中使用,用法:this.$set("key",value) |
$delete | Function | key: String | 删除数据属性,如果在onInit函数中使用,用法:this.$delete("key") |
元素属性/方法 | 类型 | 参数 | 描述 |
---|---|---|---|
$set | Function | key: String value: Any |
添加数据属性,用法:this.$vm("id").$set("key",value) |
$delete | Function | key: String | 删除数据属性,用法:this.$vm("id").$delete("key") |
$on | Function | eventName: String handler: Function |
在当前页面注册监听事件, 可监听$emit()、 $dispatch()、 $broadcast()等触发的自定义事件,不能用于注册组件节点的事件响应 |
$off | Function | eventName: String handler: Function |
移除事件监听,参数 fnHandler 为可选,传递仅移除指定的响应函数,不传递则移除此事件的所有监听 |
$emit | Function | eventName: String data: Object |
触发当前实例监听事件函数,与 $on() 配合使用 |
* 注意,获取元素应该在页面已渲染后,如 onReady 事件中或 onReady 事件执行完以后。
页面设计布局和尺寸
采用 border-box 模型且不支持 box-sizing 属性
设计稿1px / 设计稿基准宽度 = 框架样式1px / 项目配置基准宽度(项目配置基准宽度:/src/manifest.json 中 config.designWidth 的值,默认750)
CSS
可以使用内联样式、tag选择器、class选择器、id选择器来为组件设置样式
仅可以使用并列选择、后代选择器、子代选择器
支持@import引入外部样式、内联样式、行内样式
颜色值不支持缩写,伪类支持不完全(支持:disabled,:checked,:focus等)
通用通用事件:click, longpress, focus, blur, appear(组件出现),disappear(组件消失),swipe(快速滑动,参数direction:[left|right|up|down])
通用属性: id, class, style, if, elif, else, for, show, disabled 等;
通用样式:width, height, padding, padding-, margin, margin-, border, border-style, border-width, border-color, border--color, border--width, border-radius, border---radius, background-color, background-size, background-image(仅本地图片), background-repeat, opacity, display(flex|none), flex, flex-grow, flex-shrick, flex-basis, position(none|fix), linear-gradient, repeating-inear-gradient, transform-origin, animation, animation-name, animation-delay, animation-duration, animation-iteration-count, animation-timing-function, animation-fill-mode, @key-frames(background-color|opacity|width|height|transform), transform(translate|translateX|translateY|rotate|rotateX|rotateY|scale|scaleX|scaleY)(以上*代表枚举[left|right|top|bottom], 具体和 css 一致。注:缩写形式和展开形式不要同时使用)
组件默认支持通用事件、属性和样式
支持样式 flex-direction, flex-wrap, justify-content, align-items, align-content
支持属性 target 和 placement
支持样式 mask-color
支持事件 visibilitychange
自组件只能是
支持属性 offset 和 refreshing
支持样式 background-color 和 progress-color
支持事件 refresh
支持属性 type(值为 html)
支持div样式, height 无效
不支持子组件
支持div样式
支持属性 index, interval, autoplay 和 indicator(是否显示indicator)
支持样式 indicator-color, indicator-selected-color 和 indicator-size
支持事件 change
支持方法 swipeTo(index)
支持属性 index
支持事件 change
子组件仅支持最多一个
支持属性 mode(scrollable|fix)
支持样式 height
支持事件 visibilitychange
支持属性 target 和 placement
支持样式 mask-color
支持事件 visibilitychange
: 开发者在页面中实现长列表或者屏幕滚动等效果时,习惯使用div组件做循环遍历
子组件必须是
支持属性 scrollpage,默认关闭,标志是否将顶部页面中非的元素随
一起滚动。开启 scrollpage 会降低
渲染性能
组件的性能优化分为: 精简 DOM 层级、复用
支持 flex-direction 和 column
具有方法scrollTo(num)和事件scroll, scrollBottom, scrollTop
的子组件可以是任何标签或除以外的组件
有一个属性 type,type 值相同的
支持
支持属性 href
href 属性值可根据路由配置
href还支持http和https开头的网址,点击后会打开webview加载网页
href还可以通过“?param1=value1”的方式添加参数,参数可以在页面中通过this.param1的方式使用
子组件仅支持
仅支持 `text
支持 sms, tel, mailto
支持样式 lines, color, font-style, font-weight(normal|bold),text-decoration, text-align, line-height, text-overflow
: 图片
支持属性 src 和 alt
支持样式 resize-mode(cover|contain|stretch|center)
不支持子组件
支持属性 percent 和 type(horizontal|circular)
支持样式 color 和 stroke-width
支持事件 visibilitychange
不支持子组件
支持属性 numstars(总数), stepsize(步长), indicator(是否可操作)和 rating(值)
支持样式 star-background, star-secondary, star-foreground(三种状态的图片)
支持事件 change,不支持click、longpress事件
不支持子组件
: 格式化的文本
不支持 show 和 disabled 属性
支持样式 color, font-size, font-style, font-weight(normal|bold),text-decoration
不支持任何事件
不支持子组件
支持样式 lines, color, font-style, font-weight(normal|bold),text-decoration, text-align, line-height, text-overflow
: 接收用户的输入
不支持子组件
支持属性 type(button|checkbox|radio|text|email|date|time|number|password), name, value, checked 和 placeholder
支持样式 color, placeholder-color, width, height 和 font-size
支持事件 change
支持方法 focus()
: 为input、textarea组件定义标注
不支持子组件
支持属性 target
支持样式 lines, color, font-style, font-weight(normal|bold),text-decoration, text-align, line-height, text-overflow
不支持事件
: : 下拉菜单
仅支持
不支持 click 事件, 支持 change 事件
不支持子组件
支持属性 min, max, value 和 step
支持样式 color, selected-color, padding 仅支持 left 和 right
支持事件 change
不支持子组件
支持属性 checked
支持事件 change