以往的手机端应用主要有两种方式:网页、原生应用;
网页: 无需安装,却体验不是很好;
原生应用: 体验流畅,却需要从应用商店下载安装,难以一步直达用户;
快应用的出现,目的就是解决这个痛点,希望能够让用户无需下载安装,并且还能流畅的体验应用内容。
快应用最终选择使用前端技术栈开发,原生渲染,同时具备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浏览器(用于调试),即可。
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,样式设置:
内联样式
ID选择器
class选择器
tag选择器
3,Flex布局:就是前端常用的flex布局,没什么不同,div标签是最常用的flex容器,需要注意的是,text、a、span、label 组件为文本容器组件,其它组件不能直接放置文本内容。
4,可以引入less、postcss等。
for
{{personIndex}}.{{personItem.name}}
show && if
1,当 if/elif 指令的值为 false 时,节点会从页面中移除,当 if/elif 指令值为 true,组件会动态插入节点中;
2,当 show 指令的值为 true 时,节点可见, 当其值为 false 时,组件不可见,但节点仍会保留在页面 DOM 结构中;
3,if/elif/else 节点必须是相邻的兄弟节点
显示隐藏:
show: 渲染但控制是否显示
条件指令:
if: if条件
elif: elif条件
else: 其余
block:block 组件是表达逻辑区块的组件,没有对应的Native组件。可以使用实现更为灵活的"列表/条件渲染",如在上使用 for 指令和 if 指令。
点击:控制是否显示城市
城市:{{city.name}}
景点:{{$item.name}}
slot:插槽,类似于其他框架的内容分发,在快应用中也实现了一套内容分发的 API,我们可以使用 slot 组件作为承载分发内容的出口。
1,快应用是组件化开发的,页面都是由各个组件组成,也有父组件、子组件的概念,组件之间传递数据等等俗的不能再俗的东西,这里都有。
2,熟悉自定义组件的开发,了解父子组件之间的通信方式,如:props,data, d i s p a t c h ( ) , dispatch(), dispatch(),broadcast(),$emit等。
3,组件的引入:快应用中是通过标签引入组件,如下面代码所示
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网页想获取系统功能可谓是困难重重,寸步难行,甚至不可能
以地理定位来说明它的用法
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}`)
}
})