一、快应用诞生的背景——想得美
以往的手机端应用主要有两种方式:网页、原生应用;
网页: 无需安装,却体验不是很好;
原生应用: 体验流畅,却需要从应用商店下载安装,难以一步直达用户;
快应用的出现,目的就是解决这个痛点,希望能够让用户无需下载安装,并且还能流畅的体验应用内容。
二、快应用的具体形态——前端工程师接盘
快应用最终选择使用前端技术栈开发,原生渲染,同时具备H5与原生应用的双重优点,开发者使用的前端技术栈资料多,学习成本底,语法形态貌似VUE,其本质还是安卓。只不过,开发者变成了前端开工程师,不用安装,在负一屏搜索,然后秒开,体积都很小,可以生成桌面快捷方式。
三、 快应用联盟——友商也有团结一致的时候
快应用在中国起源也是有其根深蒂固的原因,因为中国的安卓手机已经是一片红海,几乎占领了全世界,好在中国的手机厂商联合起来推出了快应用技术标准,如果各自为战,形成不了统一的标准,技术很难推广,好在没有哪家厂商垄断手机市场,另外,快应用只用于安卓系统
华为、小米、OPPO、VIVO、中兴、金立、联想、魅族、努比亚
四、快应用发展——年轻、不温不火
2018年3月20日在北京推出“快应用”标准,对标腾讯小程序。
快应用最初是由小米公司最开始做的,那时候还不叫快应用,叫直达服务,那时候还是2016年,当时,小米只是为了培养自己的系统也就是MIUI的移动互联网应用生态,后来得到了大家的认可由九大厂商共同制定标准,并且取名快应用。
快应用在短短的一年内经历了1010、1020、1030、1040、1050的版本迭代,但是就我个人开发经验而言,每次都是常规升级,并没有革命性升级,但是,却越来越完善。
五、快应用开发技术栈——前端
1,HTML
2,CSS
3,JavaScript,文件以.ux结尾
4,和React、VUE一样,采用数据驱动的方式渲染页面,不直接操作DOM,MVVM模式,组件化开发、但是快应用并没有类似于React的Redux一样有一个全局的store,用于驱动相关的组件、页面,快应用也有自己全局数据存储区,但是,它仅仅只是存储,不像Redux那样富有灵魂。
5,一个安卓手机、同一个WiFi(USB方式就不需要同一个WiFi,但是需要数据线),Chrome浏览器(用于调试),即可。
六、快应用开发环境、工具
- 需安装8.0以上版本的 NodeJS (建议使用 10.0+ 以上)
- hap-toolkit,npm可以下载,就一个工具包,帮助开发者通过命令行工具辅助开发工作的完成,主要包括创建模板工程,升级工程,编译,调试等功能。
- 调试器,这是一个安卓应用(apk),用于开发阶段调试,功能如下:
3.1、扫码安装快应用,配置 HTTP 服务器地址,下载 rpk 包,并唤起平台运行 rpk 包
3.2、本地安装快应用:选择手机文件系统中的rpk包,并唤起平台运行rpk包
3.3、在线更新快应用:重新发送 HTTP 请求,更新 rpk 包,并唤起平台运行 rpk 包
3.4、开始调试快应用:唤起平台运行 rpk 包,并启动远程调试
七、快应用工程化
1,因为前面讲了需要安装Node,可以猜到,快应用也采用了npm安装包裹的方式,需要什么包,直接用npm install即可,但是快应用目前生态、社区并不丰富,所以几乎也没什么可下的。
2,前面讲了安装hap-toolkit,它提供了一个叫做hap的命令,下面介绍一下几个常用的命令,其实命令很少,总共也没几个:
2.1、hap init demo:初始化工程;
2.2、npm install:安装模块都在node_modules里,这和普通前端开发是一样的;
2.3、hap build:手动编译项目,编译打包成功后,项目根目录下会生成文件夹:build、dist
build:临时产出,包含编译后的页面 js,图片等
dist:最终产出,包含 rpk 文件。其实是将 build 目录下的资源打包压缩为一个文件,后缀名为rpk,这个rpk文件就是项目编译后的最终产出
2.4、hap watch:自动编译项目,每次修改源代码,你都想重新编译生成新的rpk安装包
2.5、hap server --port 8080,启动一个HTTP服务器,作用是调试,我们在讲调试器的时候列举了1,2,3,4等等,开启这个服务器就是为了扫码安装、在线更新快应用,调试
2.6、hap debug
2.7、hap release
八、目录结构,重点文件的讲解
前面不是讲了初始化工程 hap init projectName的命令么,那么这个命令到底会生成什么鬼哦?
├── sign rpk包签名模块
│ └── debug 调试环境
│ ├── certificate.pem 证书文件
│ └── private.pem 私钥文件
├── src
│ ├── Common 公用的资源和组件文件
│ │ └── logo.png 应用图标
│ ├── Demo 页面目录
│ | └── index.ux 页面文件,可自定义页面名称
│ ├── app.ux APP文件,可引入公共脚本,暴露公共数据和方法等
│ └── manifest.json 项目配置文件,配置应用图标、页面路由等
└── package.json 定义项目需要的各种模块及配置信息
1,package.json,这里不想赘述,和React、vue常规前端的package.json是一样的;
2,src/app.ux:整个快应用项目的入口文件,可以在这里做工程的初始化工作;
3,src/manifest.json:工程配置文件,参加这里 点我啊
4,src/common:可以将应用的图片放这里
九、快应用生命周期 —— 不细讲
1,页面的生命周期:onInit、onReady、onShow、onHide、onDestroy、onBackPress、onMenuPress
2,页面的状态:显示、隐藏、销毁
3,APP 的生命周期:onCreate、onDestroy
十、页面样式、布局
1,盒模型:只支持border-box模式,
2,样式设置:
<template>
<div class="tutorial-page">
<text style="color: #FF0000;">内联样式</text>
<text id="title">ID选择器</text>
<text class="title">class选择器</text>
<text>tag选择器</text>
</div>
</template>
<style>
.tutorial-page {
flex-direction: column;
}
/* tag选择器 */
text {
color: #0000FF;
}
/* class选择器(推荐) */
.title {
color: #00FF00;
}
/* ID选择器 */
#title {
color: #00A000;
}
/* 并列选择 */
.title, #title {
font-weight: bold;
}
/* 后代选择器 */
.tutorial-page text {
font-size: 42px;
}
/* 直接后代选择器 */
.tutorial-page > text {
text-decoration: underline;
}
</style>
3,Flex布局:就是前端常用的flex布局,没什么不同,div标签是最常用的flex容器,需要注意的是,text、a、span、label 组件为文本容器组件,其它组件不能直接放置文本内容。
4,可以引入less、postcss等。
十一、快应用框架指令——参照VUE
for
<div class="tutorial-row" for="(personIndex, personItem) in list">
<text>{{personIndex}}.{{personItem.name}}</text>
</div>
show && if
1,当 if/elif 指令的值为 false 时,节点会从页面中移除,当 if/elif 指令值为 true,组件会动态插入节点中;
2,当 show 指令的值为 true 时,节点可见, 当其值为 false 时,组件不可见,但节点仍会保留在页面 DOM 结构中;
3,if/elif/else 节点必须是相邻的兄弟节点
<template>
<div class="tutorial-page">
<text onclick="onClickShow">显示隐藏:</text>
<text show="{{showVar}}">show: 渲染但控制是否显示</text>
<text onclick="onClickCondition">条件指令:</text>
<text if="{{conditionVar === 1}}">if: if条件</text>
<text elif="{{conditionVar === 2}}">elif: elif条件</text>
<text else>else: 其余</text>
</div>
</template>
<style lang="less">
.tutorial-page {
flex-direction: column;
}
</style>
<script>
export default {
private: {
showVar: true,
conditionVar: 1
},
onInit () {
this.$page.setTitleBar({ text: '指令if与指令show' })
},
onClickShow () {
this.showVar = !this.showVar
},
onClickCondition () {
this.conditionVar = ++this.conditionVar % 3
}
}
</script>
block:block 组件是表达逻辑区块的组件,没有对应的Native组件。可以使用实现更为灵活的"列表/条件渲染",如在上使用 for 指令和 if 指令。
<template>
<div class="tutorial-page">
<text onclick="toggleCityList">点击:控制是否显示城市</text>
<div class="city" for="city in cities" if="{{showCityList === 1}}">
<text>城市:{{city.name}}</text>
<block if="{{city.showSpots}}" for="{{city.spots}}">
<text>景点:{{$item.name}}</text>
</block>
</div>
</div>
</template>
slot:插槽,类似于其他框架的内容分发,在快应用中也实现了一套内容分发的 API,我们可以使用 slot 组件作为承载分发内容的出口。
十二、快应用组件
1,快应用是组件化开发的,页面都是由各个组件组成,也有父组件、子组件的概念,组件之间传递数据等等俗的不能再俗的东西,这里都有。
2,熟悉自定义组件的开发,了解父子组件之间的通信方式,如:props,data, d i s p a t c h ( ) , dispatch(), dispatch(),broadcast(),$emit等。
3,组件的引入:快应用中是通过标签引入组件,如下面代码所示
<import name="XXX" src="url-path"></import>
4,组件通信:props:父 —> 子,子组件使用protected接收
5,组件通信:子 —> 父
父组件传递的数据本身就是对象,子组件直接修改对象中的属性,父组件的值也会发生改变,不推荐这种;
子组件通过
d
i
s
p
a
t
c
h
(
)
触
发
自
定
义
事
件
,
父
组
件
通
过
dispatch()触发自定义事件,父组件通过
dispatch()触发自定义事件,父组件通过on()监控自定义事件的触发;
子组件通过$emit()触发在节点上绑定的自定义事件来执行父组件的方法;
6,组件通信:兄弟组件通信: o n ( ) , on(), on(),emit()
十三、快应用路由
快应用的路由其实也很俗,和React之流用法上没太大区别,无非也是push、back、replace这些人间烟火,但是快应用的路由的作用可是大的很,远超过普通前端的路由。
1,导入模块及使用
import router from '@system.router'
or
const router = require('@system.router')
router.push({
uri: '/about',
params: {
body: "message"
}
})
// open web page
router.push({
uri: 'http://www.example.com'
})
// install apk
router.push({
uri: 'internal://cache/example.apk'
})
// 打开另一个快应用
router.push({
uri: 'hap://app/com.example.quickapp/page?key=value'
})
// 打开wifi设置页面
router.push({
uri: 'hap://settings/wlan_manager'
})
// replace
router.replace({
uri: '/test',
params: {
testId: '1'
}
})
// back
router.back()
// 清空所有历史页面记录,仅保留当前页面
router.clear()
十四、快应用的系统能力——五星
这个可以说是快应用相对于web页面来说的一个王炸级的优势,快应用因为本质就是安卓,所以获取系统功能犹如探囊取物,普通的web网页想获取系统功能可谓是困难重重,寸步难行,甚至不可能
- 震动
- 二维码
- 传感器
- 设备信息
- 电量信息
- 地理定位
- 联系人
- 录音
- 蓝牙
- WiFi
- 闹钟
- 系统音量
- 网络状态
- 。。。
以地理定位来说明它的用法
1,manifest.json中接口声明
{ "name": "system.geolocation" }
2,导入模块
import geolocation from '@system.geolocation'
3,示例
geolocation.getLocation({
success: function(data) {
console.log(
`handling success: longitude = ${data.longitude}, latitude = ${
data.latitude
}`
)
},
fail: function(data, code) {
console.log(`handling fail, code = ${code}`)
}
})