精华内容
下载资源
问答
  • 快应用
    千次阅读
    2021-08-01 01:03:37

    盘点MIUI里快应用2种开启方法

    2020-04-18 16:51:33

    0点赞

    0收藏

    0评论

    hello,社区的朋友们,又到了每周一更的时刻了,今天Flashcer和大家一起讨论下“快应用”!

    本期主要解决2个问题:

    第一,扫盲关于“快应用 知识点”;

    第二,分享关于MIUI里快应用2种开启方法。

    1、快应用 知识点

    (1) 快应用的前身

    从MIUI 9 开发版 8.3.29 开始,已经优化 “直达服务”,并且更名为”快应用“。

    7fb67e3c01620b158cd25a21a41436ae.png

    (2) 快应用的简介

    快应用是基于手机硬件平台的新型应用形态,标准是由主流手机厂商组成的快应用联盟联合制定,为用户提供更高效便捷的服务。

    a33d775e7665e9bf78ada4222e807889.png

    快应用具备传统APP完整的应用体验,无需安装、即点即用,占用很小的空间,可以生产桌面图标,支持推送。

    e0efe5829f4f37f9e3470660f30050d1.png

    2、如何开启MIUI里快应用?

    为了方便大家了解,我加入了小爱同学(青葱版)和米兔组成的【MIUI玩机技巧】群聊,

    如何开启MIUI里快应用,一起看看米兔是怎么解答的!

    小爱同学(青葱版): 小伙伴们,MIUI里快应用开启方法有几种?

    Flashcer: emm......这道题我不会做,呼叫米兔ing

    米兔:MIUI里快应用开启方法有2种

    米兔:应用商店、负一屏里的全局搜索

    7be7f25aaed91624943795fd744c2f68.png

    3、操作方法:

    1) 方法 1——应用商店 入口

    设置方法:

    ①打开【小米应用商店】——选择顶部的【分类】,如下图所示:

    7e0addc5ae50e1c0ed8165dbdae5b647.png

    ② 进入【分类】页面后——选择顶部【快应用】——切换到【快应用中心】页面,选择自己需要的快应用,点开即可使用!

    aec84fc93c52e940bd1c6c038cea05b7.png

    2) 方法 2——负一屏里的全局搜索 入口

    设置方法:

    切换到负一屏——双手指下拉弹出页面——找到【最近使用的快应用】

    d77b6eeb4a5f9105d622d81a8684a06f.png

    温馨提示:

    该方法使用的前提是,你先在【小米应用商店】安装过一个快应用。

    4、快应用有啥用?

    据MIUI官方介绍,“快应用最大的特点是点击就打开,也就是名字中“快”这个字的由来。

    我们以前如果使用微博,需要先下载微博App,然后安装,打开才能看,对于我这样不常看微博的人来说,是一个比较重的操作。但有时又突然想去看看某个现在热门话题,这时我会选择在搜索里搜“微博”然后点微博快应用秒开看,这个就是用快应用做的。”

    由于快应用功能类似小程序,用完即走,不占用手机太多空间,特别方便,

    本期「大F 玩机教程」结束,第2期「大F 玩机教程 02」以“盘点MIUI里快应用2种开启方法”为切入点,

    在接下来的日子里Flashcer将会持续不断地更新。

    c2ad9c123c4d84295e50d901fd065b58.png

    更多相关内容
  • 一文分析 快应用技术架构及业务前景

    千次阅读 多人点赞 2021-09-14 08:17:34
    2018年3月 华为、小米、Oppo、Vivo、中兴、联想、魅族、一加、努比亚、金立 ...新成立的快应用联盟,在快应用技术规范层面做了统一,保证快应用开发者开发的快应用,可以直接在所有快应用联盟内厂商的终端设备上运行。

    2018年3月 华为、小米、Oppo、Vivo、中兴、联想、魅族、一加、努比亚、金立 共10家国内终端厂商成立快应用联盟,并召开快应用标准发布会。
    新成立的快应用联盟,在快应用技术规范层面做了统一,保证快应用开发者开发的快应用,可以直接在所有快应用联盟内厂商的终端设备上运行。

    2018快应用联盟终端厂商

    2019年中国移动终端公司海信先后加入快应用联盟,快应用联盟终端厂商增加到12家。

    2019快应用联盟终端厂商

    2021年4月23日,快应用联盟召开2021块应用联盟开发者大会,并宣布酷派与从华为分拆出去的荣耀加入快应用联盟。

    2021块应用联盟终端厂商

    截止到2021年9月,快应用联盟终端厂商数量增加到14家,分别为:
    华为、小米、Oppo、Vivo、中兴、联想、魅族、一加、努比亚、金立、中国移动终端公司、海信、酷派、荣耀。

    一、快应用产生

    2017年1月 微信正式推出小程序,截止到2017年底 微信小程序月活已突破2亿,上线小程序已经超过58万个,微信小程序开发者超过100万,微信小程序用户累计已超过 4 亿。

    微信拥有超过10亿的使用用户,面对如此庞大的用户基数,与微信小程序的蓬勃发展,终端厂商联合起来组成快应用联盟,主要有以下两方面的原因:

    • 维护终端厂商在 应用分发、应用预装和应用营销 方面巨大收益
      对于国内终端厂商,应用分发、应用预装和应用营销方面利润巨大。而微信小程序的上线,使其在微信内形成闭环,拥有海量用户的微信App直接转变为应用分发市场,加之微信小程序的蓬勃发展,直接影响了终端厂商在应用分发方面的收益。
    • 阻击微信小程序 争夺应用分发入口的控制权
      微信拥有超过10亿的使用用户,面对如此庞大的用户基数,单打独斗并不是终端厂商最好的选择,结盟对抗、制定统一标准、共同推广,将应用分发入口牢牢地把握在自己手中,成为了国内终端厂商必然的选择。

    二、快应用介绍

    快应用宣称 以Web前端语言开发原生应用用户无需下载安装,即点即用,享受原生应用的性能体验

    快应用在实现上使用HTML5语言ES6标准的js脚本CSS3样式标准以及Flexbox布局标准进行开发,使用JS语言调用Android Framework提供的应用程序组件进行应用的渲染,并且以独立进程的形式运行在Android系统中拥有与原生应用相近的用户使用体验

    快应用开发语言

    2.1 快应用入口

    在快应用联盟的手机设备中,不同的设备厂商,其快应用入口可能略有不同。但基本存在于手机的应用市场应用市场——快应用中心负一屏桌面快应用图标等位置。
    以下为华为设备,快应用入口举例:

    快应用入口—应用市场

    快应用入口—快应用中心、负一屏、桌面图标

    2.2 快应用现状

    快应用运营方:

    快应用运营方为万咖壹联的子公司玩咖欢聚

    机型支持情况:

    截止到2020年9月,快应用联盟官方论坛公布的支持快应用的设备以及机型如下图所示:

    2020年2月快应用机型覆盖情况

    快应用的机型覆盖、场景覆盖、框架版本(2020.09更新):
    https://bbs.quickapp.cn/forum.php?mod=viewthread&tid=2524

    发展状况 2019:

    快应用联盟 生态合作方之一的轻粒子统计,曾于2020年1月14日公布《2019快应用行业报告》

    报告指出:

    • 截止到2019年12月,快应用月活3亿应用开发者1.5万
    • 快应用数量占比最多的两个品类依次为生活服务类快应用实用工具类快应用
      生活服务类快应用是与用户衣食住行相关的场景,比如附近就餐、旅馆推荐、打车服务、天气服务等;
      实用工具类快应用,如交话费、寄快递(小米手机负一屏 快应用卡片 菜鸟裹裹)。

    快应用应用品类分布图

    发展状况 2020:

    快应用运营方 玩咖欢聚 于2021年4月20日,举办快应用联盟开发者大会,其公布的数据如下:

    • 2020快应用在网设备覆盖量超过12亿;
    • 2020年快应用用户留存达70.33%;
    • 与去年相比,活跃用户稳步增长37%,活跃快应用数量稳步增长46.7%,实用工具成为用户最为活跃的快应用品类。

    注:
    以上公布的数据中,在网设备覆盖量为12亿,指的是快应用联盟设备出货量,也就是快应用联盟终端厂商累计卖出的设备数量,这些设备中仅预装了快应用运行框架的APP,可以为快应用的运行提供运行环境,并非是累计用户12亿。

    2021年4月20日快应用联盟开发者大会公布的数据中,未包含任何快应用的日活、月活已上线快应用数注册开发者数量以及累计用户数据等关键数字。

    快应用社区活跃度:

    从当前快应用开发社区、快应用Github活跃程度,可以猜测快应用发展可能非常不顺利,各种关键数据可能非常不乐观。

    • 快应用开发者社区 注册会员数量 仅2926快应用跟帖数量 仅7253。快应用开发者社区比较冷淡,开发者关注度不高。
      快应用社区注册会员数量、快应用跟帖数量
    • 快应用Github对应的 sample开发案例fork数量 仅为205点赞仅为291,猜测快应用开发者数量应该比较少,猜测仅有2~3万左右。
      快应用Github开发者fork量

    基于以上数据推测,快应用发展可能非常不顺利数据可能很不乐观

    总结

    因快应用联盟从未公布过,快应用的日活、月活已上线快应用数注册开发者数量以及累计用户数据(快应用联盟生态合作伙伴,轻粒子统计也仅在2020年1月公布过一次2019年底快应用的月活、注册开发者人数),其他关键数据均无法获取。
    仅就目前掌握的数据,就快应用发展现状进行推测:快应用发展可能非常不顺利 , 注册开发者等数据可能很不乐观

    • 从Github与社区活跃情况推测,快应用注册开发者可能仅2~3万;
    • 快应用的月活数据,更多的是靠华为、小米等终端厂商负一屏的工具类卡片来支撑,快应用用户可能都不清楚自己使用过快应用,更不用说自己到快应用中心查找相应的快应用(亲身使用发现:快应用中心 在终端应用商城App的入口也较深,不易被用户发现)。

    三、快应用技术架构

    快应用以Web前端语言开发原生应用,使用HTML5语言ES6标准的js脚本CSS3样式标准以及Flexbox布局标准进行开发,使用JS语言调用Android Framework提供的应用程序组件进行应用的渲染,并且以独立进程的形式运行在Android系统中拥有与原生应用相近的用户使用体验

    3.1 技术架构

    以下是我基于快应用开发文档反编译快应用运行框架(quickapp_platform.apk)以及参考React Native实现原理绘制的快应用技术架构图。

    快应用的技术架构

    3.1.1 快应用(xxx.rpk)

    快应用打包后为一个xxx.rpk文件,并且大小包不超过1M。

    其包结构如下图所示:
    rpk包结构

    开发快应用时,快应用工程目录结构如下所示:

    └── src
    │   ├── assets          # 公用的资源(Images/Styles/字体...)
    │   │   ├──images       # 存储 png/jpg/svg 等公共图片资源
    │   │   └──styles       # 存放 less/css/sass 等公共样式资源
    │   ├── helper          # 项目自定义辅助各类工具
    │   ├── pages           # 统一存放项目页面级代码
    │   ├── app.ux          # 应用程序代码的入口文件
    │   └── manifest.json   # 配置应用基本信息
    └── package.json        # 定义项目需要的各种模块及配置信息
    

    为保证用户在快应用中心,点击对应的快应用时可以迅速打开,供用户使用,快应用的rpk包大小要求不能超过1M,否则无法通过快应用市场审核。

    rpk包大小不超过1M

    3.1.2 快应用服务框架

    快应用的运行环境是 一个已经预装到终端手机的 App (quickapp_platform.apk):

    • 与微信小程序类似,微信小程序的运行环境由微信App来提供。
    • 而快应用的运行环境由quickapp_platform.apk来提供,quickapp_platform.apk这个App在设备出厂前已经预装到 快应用联盟终端厂商的手机中,终端手机厂商称之为快应用服务框架,实际为一个App。

    3.1.3 快应用JS与Java Native API通信

    快应用号称“以Web前端语言开发原生应用,拥有与原生应用相近的用户使用体验”,那么“通过JS调用Java Native API就是一个待解决的问题”。
    这一点上,快应用与React Native的实现是一致的,通过JavaScriptCore来实现。JavaScriptCore是开源项目WebKit代码的一部分,JavaScriptCore是WebKit内嵌的JS引擎。

    • JavaScriptCore可以实现在原生代码里面执行JavaScript 而不用通过浏览器。
    • JavaScriptCore可以把原生对象注入到JavaScript环境中。
      JavaScriptCore提供了 JS 代码与原生代码交互的能力,通过 JavaScriptCore可以实现两端的对象暴露,使得代码可以不断地在JS环境和原生环境穿梭。

    快应用的UI结构

    快应用服务框架通过JavaScriptCore开源框架实现与Android原生代码的通信,实现从JS的API到Java API的调用,从而实现使用Android原生应用组件进行渲染。

    3.2 快应用如何下载

    为保证用户在快应用中心,点击对应的快应用时可以迅速打开,供用户使用,快应用的rpk包大小要求不能超过1M,否则无法通过快应用市场审核。

    这里以小米快应用中心,点击下载快应用抓包进行举例说明。

    3.2.1 快应用中心

    打开小米快应用中心,其效果图如下所示:

    快应用中心

    3.2.2 快应用列表数据

    通过抓包,可以查看小米快应用中心列表数据。打开快应用中心时,应用列表数据中包含每个快应用的 包名 以及 描述信息

    快应用中心——快应用列表数据

    3.2.3 快应用下载地址

    以快应用 “荒野日记” 为例,用户点击 “秒开” 按钮时,快应用中心根据快应用包名请求对应快应用的下载地址

    点击秒开时——根据包名获取对应快应用的下载地址

    3.2.4 下载快应用

    仍然以快应用 “ 荒野日记 ” 为例,获取到快应用的下载地址后,直接下载对应的快应用。
    荒野日记快应用下载地址:
    https://t2.market.xiaomi.com/download/Mina/0b7295bd94ba17ad2cd7598ad80dd7ffffa435403
    下载后的快应用文件为 0b7295bd94ba17ad2cd7598ad80dd7ffffa435403,该文件虽然无扩展名,但实际一个压缩包文件(也是一个.rpk文件)。

    下载小程序

    给下载后的快应用 0b7295bd94ba17ad2cd7598ad80dd7ffffa435403 添加一个扩展名:

    下载后的小程序是一个压缩包

    解压快应用(解压.rpk文件),可以看到其符合一个.rpk文件的包结构,并且快应用中基本均为代码实现,几乎没有图片资源(为了减小快应用xxx.rpk文件的大小,提升用户下载使用快应用的体验)。

    解压后的快应用

    再对比一下.rpk文件的包结构,结构一致:
    rpk包结构

    3.3 快应用原理总结

    用户在快应用中心点击某个快应用时,快应用中心仅仅下载了一个小于1M的快应用程序入口,快应用的其他大部分媒体资源存放于远程服务端(随用户使用按需逐步下载);
    下载完成的快应用程序,其运行环境由一个叫做快应用运行框架的APP提供(快应用运行框架App在手机设备出厂时,已经预装到快应用联盟的设备中),从而在用户感知上免去了快应用的下载与安装过程,达到用户快速使用的目的。
    同时由于快应用程序包小于1M快应用功能承载能力有限,仅包含对应原生APP的部分功能或仅为某个原生游戏APP的预览版本

    3.4 快应用 VS 微信小程序

    快应用微信小程序在技术实现上基本没有差别。

    • 微信小程序的运行环境由 微信App 来提供。
    • 快应用的运行环境由 quickapp_platform.apk(快应用运行框架) 来提供。
      quickapp_platform.apk 这个App在设备出厂前已经预装到 快应用联盟终端厂商的手机中,终端手机厂商称之为 快应用服务框架 ,实际为一个App。

    微信小程序与快应用实现对比

    参考

    万咖壹联:
    http://www.wankaonline.com/home

    玩咖欢聚:
    http://www.wankacn.com/

    快应用官方:
    https://www.quickapp.cn/

    快应用介绍:
    https://www.quickapp.cn/course

    2019年快应用行业报告:
    [https://statres.qinglizi.cn/quickapp_statistics)

    快应用的机型覆盖、场景覆盖、框架版本(2020.09更新):
    https://bbs.quickapp.cn/forum.php?mod=viewthread&tid=2524

    React Native运行原理解析:
    https://cloud.tencent.com/developer/article/1036325

    详解React Native渲染原理:
    https://www.jianshu.com/p/7e7b462c187b

    深入理解JavaScriptCore:
    https://cloud.tencent.com/developer/article/1406122

    JavaScriptCore 整体介绍:
    https://zhuanlan.zhihu.com/p/29663994

    NativeJS理解和使用:
    https://www.jianshu.com/p/7b022c176a0b

    == THE END ==

    欢迎关注我的公众号

    展开全文
  • 快应用

    千次阅读 2018-03-22 13:01:02
    正所谓,“哪里有商机哪里就有竞争”,据报道,中国九大安卓手机厂商华为、小米、OPPO、vivo、中兴、金立、联想、魅族、努比亚联起手来共同对抗微信小程序的迅猛扩张,他们将于3月20日将共同启动「快应用」标准,...

    小程序自2016年推出以来,可以说是一路火爆,更是改写了移动互联网的格局,开辟了另一流量战场。正所谓,“哪里有商机哪里就有竞争”,据报道,中国九大安卓手机厂商华为、小米、OPPO、vivo、中兴、金立、联想、魅族、努比亚联起手来共同对抗微信小程序的迅猛扩张,他们将于3月20日将共同启动「快应用」标准,打造移动应用新生态,目的是遏制急剧扩张的微信小程序。

    快应用简介

    什么是快应用,快应用具有哪些特点:

    1. 快应用是基于手机硬件平台的新型应用形态,标准是由主流手机厂商组成的快应用联盟联合制定。
    2. 快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台,以平台化的生态模式对个人开发者和企业开发者全品类开放。
    3. 快应用具备传统APP完整的应用体验,无需安装、即点即用。

    打开华为市场,搜索“快应用”,可以看到很多的厂商已经上线了快应用。
    这里写图片描述
    点击一个运行,其体验丝毫不比原生体验差,下面是录的一个gif动画。
    这里写图片描述

    目前,并非所有的平台都上线了快应用,目前还有很多的厂商还在开发中,目前提供快应用的厂商有:小米、华为、金立。魅族、努比亚、OPPO、ViVo,其他平台目前还在开发中。
    这里写图片描述

    快应用上手

    官网:https://www.quickapp.cn/
    开发文档:https://doc.quickapp.cn/

    既然是快应用,那就是快、方便。快应用使用JavaScript编写,部署即可见。那么如何搭建一个快应用并发布到应用市场呢?本文就这方面给大家做一个整理。

    环境搭建

    1,安装Node
    任何使用JavaScript进行开发的平台都会用到Node,Node可以下载安装,下载的官方地址为:https://nodejs.org/en/download/。

    2,安装hap-toolkit
    使用npm安装命令安装hap-toolkit:

    npm install -g hap-toolkit
    

    安装完成后,可以通过查看版本来确认是否安装成功。

    hap -V
    

    3,创建HelloWorld
    快应用目前没有很好的开发工具,可以选择前端比较出名的一些开发工具来开发,如WebStrom、IDEA、vscode等。为了演示,本文以命令行的方式来创建一个HelloWorld项目。

    创建一个快应用文件夹,选择一个合适文件,使用命令创建项目:

    hap init <ProjectName>
    

    其中,ProjectName为你的项目名称,完成后会显示:

    prompt: Init your Project:  (helloworld) 
    

    这里写图片描述
    看到这个图不要傻傻等着,点击回车,系统会为你创建一个helloword的快应用。创建完成后,项目的目录结构如图:
    这里写图片描述
    然后,切换到helloword目录,执行npm命令行安装依赖包(webpack,babel等):

    npm install
    

    然后,运行如下命令即可在dist目录下生成rpk包。其实,这和vue开发客户端,并使用Hbuilder开发跨平台APP的思路是一致的,有兴趣的童鞋可以了解下。

    npm run build
    

    注意:如果报错遇到Cannot find module ‘…/webpack.config.js’,请重新执行一次hap update --force。这是由于高版本的npm在npm install时,会校验并删除了node_modules下部分文件夹,导致报错。而hap update --force会重新复制hap-toolkit文件夹到node_modules中。
    这里写图片描述

    然后再次执行”npm run build“,即可看到效果。
    这里写图片描述

    安装生成的包

    下载快应用提供的调试apk文件,并安装到手机上,下载地址:
    https://statres.quickapp.cn/quickapp/quickapp/201803/file/201803200129552999556.apk
    不过对于有些手机你会发现,你安装上之后,什么也干不了,颜色都是灰的。
    这里写图片描述
    请注意这很正常,你还需要安装一个平台app

    手机安装平台预览版

    使用下面地址下载预览版:
    https://statres.quickapp.cn/quickapp/quickapp/201803/file/201803200130021102030.apk
    你安装完成后应该是个白板,啥也没有,正常。你回到之前的安装调试器apk,会发现按钮都可以点击了。然后再次打开即可。
    这里写图片描述

    还记得刚才helloworld生成的rpk包么,可以使用以下的命令导入到sd卡中。

    adb push xxx.rpk  /sdacrd/
    

    push到手机根目录,然后选择本地安装,选择rpk包即可。当然,你还可以使用“扫码方式来安装”,这种方式生成二维码的命令如下:

    npm run server -- --port 8080
    

    这里写图片描述

    这里写图片描述

    好了,快应用相关的内容就普及完了,如果想要自己开发一个快应用并上架,可以参考官方的介绍。
    https://doc.quickapp.cn/

    展开全文
  • 快应用简介

    千次阅读 2019-04-20 10:01:18
    快应用是一种新的应用形态,以往的手机端应用主要有两种方式:网页、原生应用;网页无需安装,却体验不是很好;原生应用体验流畅,却需要从应用商店下载安装,难以一步直达用户;快应用的出现,就是希望能够让用户...

    快应用是一种新的应用形态,以往的手机端应用主要有两种方式:网页、原生应用;网页无需安装,却体验不是很好;原生应用体验流畅,却需要从应用商店下载安装,难以一步直达用户;快应用的出现,就是希望能够让用户无需下载安装,并且还能流畅的体验应用内容。

    为了达到上面的目标,快应用建立一种新的语言开发规范,同时提供一系列的开发套件辅助支持。简单来说,开发者主要利用前端知识与技能,以及对应的IDE,手机设备就可以做原型的开发。快应用使用前端技术栈开发,原生渲染,同时具备H5与原生应用的双重优点,开发者使用的前端技术栈资料多,学习成本底。

    2018年3月份,由小米,OPPO,VIVO,华为等10家国内主流厂商成立了快应用联盟,从技术规范层面做了统一,并保证了开发者开发的快应用可以直接在所有的联盟内厂商的手机设备上运行。

    快应用框架深度集成进各手机厂商的手机操作系统中,可以在操作系统层面形成用户需求与应用服务的无缝连接,很多只用在原生应用中才能使用的功能,在快应用中可以很方便的实现,享受原生应用体验,同时不用担心分发留存等问题,资源消耗也比较少。

    对于每台手机设备,应用可以从多个系统入口,引用用户体验产品。比如:全局搜索、负一屏、浏览器搜索等。

     

    前言

    与微信小程序的比较

    • 二者都采用前端技术栈,快应用是native 渲染,性能体验会比较好,而小程序目前是webview渲染
    • 二者开发框架和规范不同,所以代码写法上有差异,快应用的css支持能力较弱
    • 快应用基于native,可以调起丰富的系统api,小程序在此方面会有些无力

    快应用入口

    • 应用商店
    • 桌面图标
    • 全局搜索
    • 浏览器搜索
    • 网页跳转
    • 负一屏
    • 智能推送
    • 智慧识屏
    • 场景化入口(短信按钮、应用卸载替换、二维码、传送门)

    快应用优点

    • 轻松调起更多系统api
    • 各厂商的流量扶持
    • native渲染,deeplink入口,原生桌面入口,push能力

    一、环境搭建

    1.1 安装NodeJS

    需安装6.0以上版本的NodeJS

    1.2 安装hap-toolkit

    // hap -V // 会显示安装版本信息
    npm install -g hap-toolkit
    

    1.3 创建项目工程

    hap init projectName
    
    // 增加编译支持
    hap update --force
    
    cd projectName && npm i
    

    生成的目录结构

    ├── sign rpk //包签名模块
    │ └── debug //调试环境
    │ ├── certificate.pem //证书文件
    │ └── private.pem //私钥文件
    ├── src
    │ ├── Common //公用的资源和组件文件
    │ │ └── logo.png //应用图标
    │ ├── Demo //页面目录
    │ | └── index.ux //页面文件,可自定义页面名称
    │ ├── app.ux //APP文件,可引入公共脚本,暴露公共数据和方法等
    │ └── manifest.json //项目配置文件,配置应用图标、页面路由等
    └── package.json //定义项目需要的各种模块及配置信息
    
    • src:项目源文件夹
    • sign:签名模块,当前仅有debug签名,如果内测上线,请添加release文件夹,增加线上签名;签名生成方法详见文档编译工具

    编译项目

    • npm run release # 发布程序包,在 /dist/.signed.rpk,注意需要使用 release 签名模块
    • npm run build # 生成 builddist 两个目录。前者是临时产出,后者是最终产出
    • npm run watch # 文件保存时自动编译和调试

    手动编译项目

    在项目的根目录下,运行如下命令进行编译打包,生成rpk包

    npm run build
    
    • 编译打包成功后,项目根目录下会生成文件夹:builddist
    • build:临时产出,包含编译后的页面js,图片等
    • dist:最终产出,包含rpk文件。其实是将build目录下的资源打包压缩为一个文件,后缀名为rpk,这个rpk文件就是项目编译后的最终产出

    自动编译项目

    • 每次修改源代码文件后,都自动编译项目
    npm run watch
    

    在安卓手机上安装调试工具

    https://www.quickapp.cn/docCenter/post/69

    image.png

    1.4 连接手机进行调试

    注意:一定要注意手机连接的wifi与电脑所连接的网络需要在同一局域网和网段,需要能够相互访问。

    • 在项目根目录下执行如下命令,启动HTTP调试服务器:(server前需要先npm run build
    npm run server
    
    • 开发者可以通过命令行终端或者调试服务器主页看到提供扫描的二维码
    • 开发者通过快应用调试器扫码安装按钮,扫码安装待调试的rpk文件
    • 开发者点击快应用调试器中的开始调试按钮,开始调试

    打开之前安装的快应用调试助手扫描即可预览

    image.png

    扫描二维码之后点击开始调试,会调出devtool工具本地调试

    image.png

    image.png

    1.5 安装Hap Extension

    启动Visual Studio Code,打开项目,点击左上侧扩展,搜索hap,点击安装Hap Extension

    二、快应用结构分析

    2.1 文件组织

    一个应用包含:描述项目配置信息的manifest文件,放置项目公共资源脚本的app.ux文件,多个描述页面/自定义组件的ux文件

    ├── sign                            rpk包签名模块
        └── debug                       调试环境
                └── certificate.pem     证书文件
                └── private.pem         私钥文件
    ├── src
       ├── Common                       公用的资源和组件文件
                └──logo.png             应用图标
       ├── Demo                         页面目录
                └── index.ux            页面文件,可自定义页面名称
       ├── app.ux               APP文件,可引入公共脚本,暴露公共数据和方法等
       └── manifest.json                项目配置文件,配置应用图标、页面路由等
    └── package.json                    定义项目需要的各种模块及配置信息
    

    目录的简要说明如下

    • src:项目源文件夹
    • sign:签名模块(当前仅有debug签名,如果内测上线,请添加release文件夹,增加线上签名)

    2.2 源码文件

    APP,页面和自定义组件均通过ux文件编写,ux文件由template模板、style样式和script脚本3个部分组成,一个典型的页面ux文件示例如下

    <template>
      <!-- template里只能有一个根节点 -->
      <div class="demo-page">
        <text class="title">欢迎打开{{title}}</text>
        <!-- 点击跳转详情页 -->
        <input class="btn" type="button" value="跳转到详情页" onclick="routeDetail">
      </div>
    </template>
    
    <style>
      .demo-page {
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
    
      .title {
        font-size: 40px;
        text-align: center;
      }
    
      .btn {
        width: 550px;
        height: 86px;
        margin-top: 75px;
        border-radius: 43px;
        background-color: #09ba07;
        font-size: 30px;
        color: #ffffff;
      }
    </style>
    
    <script>
      import router from '@system.router'
    
      export default {
        // 页面级组件的数据模型,影响传入数据的覆盖机制:private内定义的属性不允许被覆盖
        private: {
          title: '示例页面'
        },
        routeDetail () {
          // 跳转到应用内的某个页面,router用法详见:文档->接口->页面路由
          router.push ({
            uri: '/DemoDetail'
          })
        }
      }
    </script>
    

    2.3 manifest配置

    https://doc.quickapp.cn/framework/manifest.html

    {
        # 包名,区分不同应用的唯一id,因为名称其实是可以一样的
        "package": "com.application.demo",
    
        # 应用名称
        "name": "hi",
    
        # 版本管理的话,每次更新将versionCode自增1即可
        "versionName": "1.0.0",
        "versionCode": "1",
        "minPlatformVersion": "101",
    
        # 程序的入口icon,所有关于文件的引用统一使用根目录
        # 根目录对应src文件夹
        "icon": "/Common/logo.png",
    
        # 
        "features": [
            { "name": "system.prompt" },
            { "name": "system.router" },
            { "name": "system.shortcut" }
        ],
    
        "permissions": [
            { "origin": "*" }
        ],
    
        # 配置相关
        "config": {
            # 这里的设置是log输出的最低等级
            # 如果是warn的话,info类型将不会输出
            # 等级请参考js中的console日志
            "logLevel": "off"
        },
    
        # 路由
        # 这里会配置应用入口的页面
        # 所有的页面都需要在这里配置
        # 会把页面与对应的页面文件对应起来
        # 经过配置之后可以通过/Demo访问到Demo目录下的index.ux页面
        "router": {
            "entry": "Demo",
            "pages": {
                "Demo": {
                    # 这里对应的Demo文件夹里的index.ux
                    "component": "index"
                },
                "DemoDetail": {
                    "component": "index"
                },
                "About": {
                    "component": "index"
                }
            }
        },
        
        # 配置页面UI显示
        # 主要分为两种,页面公有与页面私有
        "display": {
            # 这三个都是所有页面公有的,顶部titleBar内容
            "titleBarText": "public title"
            "titleBarBackgroundColor": "#f2f2f2",
            "titleBarTextColor": "#414141",
    
            # 会增加一个导航栏
            "menu": true,
    
            # 页面私有内容
            "pages": {
                "Demo": {
                    # 这里面的内容就是每个页面私有的了
                    "titleBarText": "示例页",
                    "menu": false
                },
                "DemoDetail": {
                    "titleBarText": "详情页"
                },
                "About": {
                    "menu": false
                }
            }
        }
    }
    
    • package 应用包名,确认与原生应用的包名不一致,推荐采用com.company.module的格式,如:com.example.demo
    • name 应用名称,6个汉字以内,与应用商店保存的名称一致,用于在桌面图标、弹窗等处显示应用名称
    • icon 应用图标,提供192x192大小的即可
    • versionName 应用版本名称,如:"1.0"
    • versionCode 应用版本号,从1自增,推荐每次重新上传包时versionCode+1
    • minPlatformVersion 支持的最小平台版本号,兼容性检查,避免上线后在低版本平台运行并导致不兼容;如果不填按照内测版本处理
    • features 接口列表,绝大部分接口都需要在这里声明,否则不能调用,详见每个接口的文档说明
    • config 系统配置
      • logLevel:打印日志等级,分为off,error,warn,info,log,debug
      • designWidth:页面设计基准宽度,根据实际设备宽度来缩放元素大小
    • router 路由信息
      • entry:首页名称
      • pages:页面配置列表,key值为页面名称(对应页面目录名,例如Hello对应'Hello'目录),value为页面详细配置page,详见下面说明
      • router.page 用于定义单个页面路由信息
        • component: 页面对应的组件名,与ux文件名保持一致,例如'hello' 对应 'hello.ux'
        • path 页面路径,例如“/user”,不填则默认为/<页面名称>。path必须唯一,不能和其他pagepath相同。下面pagepath因为缺失,会被设置为“/Index”"Index": {"component": "index"}
        • filter: 声明页面可以处理某种请求
    • display UI显示相关配置
      • backgroundColor 窗口背景颜色
      • fullScreen 是否是全屏模式,默认不会同时作用于titleBartitleBar需要继续通过titleBar控制
      • titleBar 是否显示titleBar
      • titleBarBackgroundColor标题栏背景色
      • titleBarTextColor 标题栏文字颜色
      • titleBarText 标题栏文字(也可通过页面跳转传递参数(titleBarText)设置)
      • menu 是否显示标题栏右上角菜单按钮
      • pages 各个页面的显示样式,key为页面名(与路由中的页面名保持一致),value为窗口显示

    2.4 app.ux

    当前app.ux编译后会包含manifest配置信息(可以在npm run build之后查看文件内容),所以请不要删除/**manifest**/的注释内容标识

    • 您可以在<script>中引入一些公共的脚本,并暴露在当前app的对象上,如下所示,然后就可以在页面ux文件的ViewModel中,通过this.$app.util访问

    2.5 style样式

    • 样式布局采用CSS Flexbox(弹性盒)样式

    支持2种导入外部文件的方式

    <!-- 导入外部文件, 代替style内部样式 -->
    <style src="./style.css"></style>
    
    <!-- 合并外部文件 -->
    <style>
      @import './style.css';
      .a {
      }
    </style>
    

    模板内部样式

    <!-- 内联inline -->
    <div style="color:red; margin: 10px;"/>
    <!-- class声明 -->
    <div class="normal append"/>
    

    样式预编译

    目前支持less, sass的预编译

    <!--导入外部文件, 代替style内部样式-->
    <style lang="less" src="./lessFile.less"></style>
    
    <!--合并外部文件-->
    <style lang="less">
      @import './lessFile.less';
      .page-less {
        #testTag {
          .less-font-text, .less-font-comma {
            font-size: 60px;
          }
        }
      }
    </style>
    
    <script>
      /**
       * 应用级别的配置,供所有页面公用
       */
      import util from './util'
    
      export default {
        showMenu: util.showMenu,
        createShortcut: util.createShortcut
      }
    </script>
    

    2.6 template模板

    <!-- temp.ux -->
    <import name="hint" src="./hint-modal"></import>  <!-- 引入外部模板 -->
    <import src="./table"></import>  <!-- 引入外部模板 -->
    
    <template>
      <div class="container">
          <div class="mod-header">
              <text class="mod-title" style="color: red; margin: 10px;">{{title}}</text>    <!-- 行内样式 -->
              <text class="mod-detail" onclick="showDetail">?</text>    <!-- 无参事件绑定 -->
          </div>
          <div class="mod-content">
              <!-- block 用来表示逻辑,不渲染 -->
              <block for="totalData">   <!-- for 循环遍历数组 $idx, $item 分别为数组的索引和值-->
                  <!-- 事件绑定 -->
                  <div onclick="onTabClick($idx)" class="item {{tabIndex === $idx && 'active'}}"> <!-- 支持简单表达式 -->
                      <text class="{{tabIndex === $idx && 'text-active'}}">{{($item || {}).name}}</text>
                      <text class="{{tabIndex === $idx && 'text-active'}}">{{($item || {}).value}}</text>  <!-- 布尔值、null、undefined、'' 不渲染,其余包括 falsy 值一律渲染 -->
                  </div>
              </block>
          </div>
          <image class="mod-like" if="{{isLike}}" /> <!-- 支持if elif else, 必须是相邻节点 -->
          <image class="mod-dislike" else />
          <table data={{dataList}}></table>  <!-- 传入属性值,使用外部模板-->
          <hint show="{{isHintShown}}">
              This is children of hint templete.
          </hint>   <!-- 使用外部模板 -->
          <!-- if 和 show 的区别:if 为 false 分支的节点不会渲染进 DOM 树,而 show 为 false 的节点会渲染,只是 display: none; -->
      </div>
    </template>
    
    <style lang="less" src="./lessFile.less"></style>   <!-- 引入外部 CSS/LESS -->
    
    <style lang="less">
      /* 引入外部 CSS/LESS */
      @import '../Common/global.less';
    
      .container{
        /* 定义样式,less 支持 */
      }
    </style>
    
    <script>
      import fetch from "@system.fetch"    // 引入系统 js
      import conf from './globalConf';     // 引入外部 js
      
      export default {
        props: ['title', 'dataList'],  // 传入属性:必须字母开头,全小写、数字和 `-` ,不能保留字和函数,不能以符号开头
        public: {
          // 定义变量,会被 props 和内部请求覆盖
        },
        private: {
          // 定义变量,不会被 props 覆盖
        },
        protected: {
          // 定义变量,不会被 props 覆盖, 但会被内部请求覆盖(获得通过 a 标签和 router 传递的参数)
        }
        data :{   // data 不能和 public、private、protected 一起使用,data 也可以是 function(返回 data 对象,onInit之前执行)
          // 定义变量:不能保留字和函数,不能以符号开头
          totalData: [{name: 'a',value: 97},{name: 'b',value: 98}];
            // 定义变量,会被 props 覆盖
        },
        onTabClick(index){    // 内部事件定义
          console.log(index);
        },
        events: {
           onIDChange(){
              // 外部事件定义
           }
        }
      }
    </script>
    
    <!-- hint.ux -->
    <template>
      <text><slot></slot></text>          <!-- slot: 获取该数据的引用的 children, 该例中即:This is children of hint templete. -->
    </template>
    

    2.7 script脚本

    2.7.1 模块声明

    可以通过import引入功能模块,在代码中调用模块方法

    import fetch from "@system.fetch"
    

    也可以一次引入所有的模块,例如

    import system from "@system"
    
    • 在代码中使用system.network来调用接口方法

    2.7.2 对象

    2.7.2.1 页面级组件

    data(废弃)

    • 页面级组件的数据模型,能够转换为JSON对象
    • 如果是函数,返回结果必须是对象,在组件初始化时会执行函数获取结果作为data的值
    • 使用data方式声明的属性会被外部数据覆盖,因此存在一定安全风险,推荐使用下面的public,protected,rivate来声明属性(注意:它们不能与data同时声明)

    public

    页面级组件的数据模型,影响传入数据的覆盖机制:public内定义的属性允许被传入的数据覆盖,如果外部传入数据的某个属性未被声明,在public中不会新增这个属性

    protected

    页面级组件的数据模型,影响传入数据的覆盖机制:protected内定义的属性,允许被应用内部页面请求传递的数据覆盖,不允许被应用外部请求传递的数据覆盖

    private

    页面级组件的数据模型,影响传入数据的覆盖机制:private内定义的属性不允许被覆盖

     export default {
        props: ['title', 'dataList'],  // 传入属性:必须字母开头,全小写、数字和 `-` ,不能保留字和函数,不能以符号开头
        public: {
          // 定义变量,会被 props 和内部请求覆盖
        },
        private: {
          // 定义变量,不会被 props 覆盖
        },
        protected: {
          // 定义变量,不会被 props 覆盖, 但会被内部请求覆盖(获得通过 a 标签和 router 传递的参数)
        }
        data :{   // data 不能和 public、private、protected 一起使用,data 也可以是 function(返回 data 对象,onInit之前执行)
          // 定义变量:不能保留字和函数,不能以符号开头
          totalData: [{name: 'a',value: 97},{name: 'b',value: 98}];
            // 定义变量,会被 props 覆盖
        },
        onTabClick(index){    // 内部事件定义
          console.log(index);
        },
        events: {
           onIDChange(){
              // 外部事件定义
           }
        }
      }
    

    2.7.2.2 自定义组件

    data

    自定义组件的数据模型,能够转换为JSON对象;属性名不能以$或_开头, 不要使用for, if, show, tid等保留字
    如果是函数,返回结果必须是对象,在组件初始化时会执行函数获取结果作为data的值

    props

    • 定义组件外部可传入的所有属性
    • 在模板代码中,请使用短横线分隔命名代替驼峰命名。如,属性定义props: ['propA'],可通过<tag prop-a='xx'>方式传递到组件内部

    prop验证

    在自定义组件中,可将props定义为带验证需求的对象。其中,key为属性名,value为属性对应的验证需求。验证失败则输出错误提示日志,增加prop验证有利于规范自定义组件的使用

    属性类型描述
    type-检查属性值的类型。支持单一类型和多种可能类型,可在原生和自定义构造函数中任意选择,单独或组合使用。原生构造函数:String Number Boolean Function Object Array Symbol
    default-设置属性的默认值
    requiredBoolean设置属性是否必填
    validatorFunction设置自定义验证函数。若函数的返回值为真,则通过验证;否则验证失败
    export default {
        props: {
          // 单一类型检查的简写
          propA: Number,
          // 多种可能类型的简写
          propB: [String, Number],
          // 必填的字符串
          propC: {
            type: String,
            required: true
          },
          // 带默认值的数字
          propD: {
            type: Number,
            default: 100
          },
          // 带有默认值的对象
          propE: {
            type: Object,
            default () {
              return { message: 'hello' }
            }
          },
          // 自定义验证函数
          propF: {
            validator (value) {
              return value === 'hello'
            }
          }
        }
      }
    

    2.7.2.3 公共对象

    属性类型描述
    $appObject应用对象
    $pageObject页面对象
    $validBoolean页面对象是否有效
    $visibleBoolean页面是否处于用户可见状态

    2.7.2.4 应用对象

    可通过$app访问

    属性类型描述
    $defObject使用this.$app.$def获取在app.ux中暴露的对象
    $dataObject使用this.$app.$data获取在manifest.jsonconfig.data中声明的全局数据

    2.7.2.5 页面对象

    可通过$page访问

    属性类型描述
    actionString获取打开当前页面的action。仅在当前页面是通过filter匹配的方式打开时有效,否则为undefined
    uriString获取打开当前页面的uri。仅在当前页面是通过filter匹配的方式打开时有效,否则为undefined

    2.7.3 方法

    2.7.3.1 数据方法

    属性类型参数描述
    $setFunctionkey: String value: Any添加数据属性,用法:this.$set('key',value) this.$vm('id').$set('key',value)
    $deleteFunctionkey: String删除数据属性,用法:this.$delete('key') this.$vm('id').$delete('key')

    2.7.3.2 公共方法

    属性描述
    $element获取指定id的组件dom对象,如果没有指定id,则返回根组件dom对象用法:<template> <div id='xxx'></div> </template> this.$element('xxx') 获取idxxxdiv组件实例对象 this.$element() 获取根组件实例对象
    $root获取顶层ViewModel
    $parent获取父亲ViewModel
    $child获取指定id的自定义组件的ViewModel用法:this.$child('xxx') 获取idxxxdiv组件ViewModel
    $vm deprecated请使用上面this.$child('xxx')替代
    $rootElement deprecated请使用上面this.$element()替代
    $forceUpdate更新ViewModel数据,可能会触发DOM操作,如:创建节点、更新节点、删除节点等;这些DOM操作不一定在数据更新时立即执行,而是在开发者的业务代码执行后触发;若开发者期望数据更新时立即执行相应的DOM操作,可使用:this.$forceUpdate();一般不推荐使用

    2.7.3.3 事件方法

    属性参数描述
    $ontype: String 事件名
    handler: Function事件句柄函数
    添加事件处理句柄用法:this.$on('xxxx', this.fn) fn是在<script>中定义的函数
    $offtype: String 事件名
    handler: 事件句柄函数
    删除事件处理句柄用法:this.$off('xxxx', this.fn) this.$off('xxx') 删除指定事件的所有处理句柄
    $dispatchtype: String 事件名向上层组件发送事件通知用法:this.$dispatch('xxx')正常情况下,会一直向上传递事件(冒泡)如果要停止冒泡,在事件句柄函数中调用evt.stop()即可
    $broadcasttype: String 事件名向子组件发送事件通知用法:this.$broadcast('xxx')正常情况下,会一直向下传递事件如果要停止传递,在事件句柄函数中调用evt.stop()即可
    $emittype: String 事件名
    data: Object 事件参数
    触发事件,对应的句柄函数被调用用法:this.$emit('xxx') this.$emit('xxx', {a:1})传递的事件参数可在事件回调函数中,通过evt.detail来访问,例如evt.detail.a
    $emitElementtype: String 事件名
    data: Object 事件参数
    id: String 组件id (默认为-1 代表根元素)
    触发组件事件,对应的句柄函数被调用用法:this.$emitElement('xxx', null, 'id') this.$emitElement('xxx',{a:1})传递的事件参数可在事件回调函数中,通过evt.detail来访问,例如evt.detail.a
    $watchdata: String 属性名, 支持'a.b.c'格式,不支持数组索引
    handler: String 事件句柄函数名,函数的第一个参数为新的属性值,第二个参数为旧的属性值
    动态添加属性/事件绑定,属性必须在data中定义,handler函数必须在<script>定义;当属性值发生变化时事件才被触发用法:this.$watch('a','handler')

    2.7.3.4 应用方法

    可通过$app访问

    属性描述
    exit退出快应用,结束应用生命周期。
    调用方法:this.$app.exit()

    2.7.3.5 页面方法

    可通过$page访问

    属性参数描述
    setTitleBartext: String 标题栏文字
    textColor: String 文字颜色
    backgroundColor: String 背景颜色
    backgroundOpacity : Number背景透明度
    menu : Boolean 是否在标题栏右上角显示菜单按钮
    设置当前页面的标题栏用法:this.$page.setTitleBar({text:'Hello', textColor:'#FF0000', backgroundColor:'#FFFFFF', backgroundOpacity:0.5, menu: true})
    finish从本页面退出,结束页面生命周期。调用方法:this.$page.finish()

    2.8 指令

    for

    for指令用于循环输出一个数组类型的数据

    • 自定义变量表示for指令的数组索引和数组元素时,变量名不可以用$_开头;
    <template>
      <div class="tutorial-page">
        <!-- 方式1:默认$item代表数组中的元素, $idx代表数组中的索引 -->
        <div class="tutorial-row" for="{{list}}">
          <text>{{$idx}}.{{$item.name}}</text>
        </div>
        <!-- 方式2:自定义元素变量名称 -->
        <div class="tutorial-row" for="value in list">
          <text>{{$idx}}.{{value.name}}</text>
        </div>
        <!-- 方式3:自定义元素、索引的变量名称 -->
        <div class="tutorial-row" for="(personIndex, personItem) in list">
          <text>{{personIndex}}.{{personItem.name}}</text>
        </div>
      </div>
    </template>
    
    <style lang="less">
      .tutorial-page {
        flex-direction: column;
        .tutorial-row {
          width: 85%;
          margin-top: 10px;
          margin-bottom: 10px;
        }
      }
    </style>
    
    <script>
      export default {
        private: {
          list: [
            {name: 'aa'},
            { name: 'bb' }
          ]
        },
        onInit () {
          this.$page.setTitleBar({ text: '指令for' })
        }
      }
    </script>
    

    指令if与指令show

    • if条件指令,是指if/elif/else这3个相关指令,用于控制是否增加或者删除组件;
    • show指令,是指是否显示组件,用于控制组件的显示状态,并不会从DOM结构中删除
    <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>
    
    • if/elif指令的值为false时,节点会从页面中移除,当if/elif指令值为true,组件会动态插入节点中;
    • show指令的值为true时,节点可见, - 当其值为false时,组件不可见,但节点仍会保留在页面DOM结构中

    组件block

    block组件是表达逻辑区块的组件,没有对应的Native组件。可以使用<block>实现更为灵活的"列表/条件渲染"。如在<block>上使用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>
    
    <style lang="less">
      .tutorial-page {
        flex-direction: column;
      }
      .city {
        flex-direction: column;
      }
    </style>
    
    <script>
      import {dataDirective} from '../../Common/js/data'
    
      export default {
        private: {
          showCityList: 1,
          cities: dataDirective
        },
        onInit () {
          this.$page.setTitleBar({ text: '组件block' })
        },
        toggleCityList () {
          this.showCityList = this.showCityList === 1 ? 0 : 1
        }
      }
    </script>
    

    组件slot

    slot节点用于向开发者额外开发的自定义ux组件中插入内容

    • 通常自定义组件的模板中提供slot组件,当该组件被引入到页面组件中后,开发者可以灵活定义该自定义组件内部的子内容
    //自定义组件part1.ux
    
    <!-- par1.ux -->
    <template>
      <div>
        <text>{{ header }}</text>
        <slot></slot>
        <text>{{ footer }}</text>
      </div>
    </template>
    
    <script>
      export default {
        props: [
          'header', 'footer'
        ]
      }
    </script>
    
    //自定义组件使用者页面index.ux
    
    <!-- index.ux -->
    <import src="./part1"></import>
    <template>
      <part1 class="component" header="{{header}}" footer="{{footer}}">
        <text>slot节点内容</text>
      </part1>
    </template>
    
    <style>
      .component {
        flex-direction: column;
      }
    </style>
    
    <script>
      export default {
        private: {
          header: 'HEAD',
          footer: 'FOOT'
        },
        onInit () {
          this.$page.setTitleBar({ text: '组件slot' })
        }
      }
    </script>
    

    在子组件中使用slot组件,使得子组件接纳调用者传入的子内容,从而动态渲染子组件,得到最终的页面

    三、生命周期

    3.1 APP的生命周期

    当前为APP的生命周期提供了两个回调函数:onCreate, onDestroy;可在app.ux中定义回调函数

    image.png

    import {
      natives
    } from './util/asyncNatives'
    
    export default {
      onCreate () {
        console.info('Application onCreate')
      },
      onDestroy () {
        console.info('Application onDestroy')
      },
      // 暴露给所有页面,在页面中通过:this.$app.$def.method1()访问
      method1 () {
        console.info('这是APP的方法')
      },
      // 暴露给所有页面,在页面中通过:this.$app.$def.data1访问
      data1: {
        name: '这是APP存的数据'
      },
      natives
    }
    
    • app.ux中,开发者可以做一些独立于页面的操作。比如:引入公共的JS资源,然后暴露给所有页面
    • app.ux中,通过this.$def访问app.ux中定义的数据和方法
    console.info(`获取:APP文件中的数据:${this.$def.data1.name}`)
    console.info(`执行:APP文件中的方法`, this.$def.method1())
    console.info(`获取:manifest.json的应用名称:${this.$def.manifest.name}`)
    console.info(`获取:manifest.json的config.data的数据:${this.$data.name}`)
    

    pageName.ux中,通过this.$app.$def访问app.ux中定义的数据和方法

    console.info(`获取:APP文件中的数据:${this.$app.$def.data1.name}`)
    console.info(`执行:APP文件中的方法`, this.$app.$def.method1())
    console.info(`获取:manifest.json的应用名称:${this.$app.$def.manifest.name}`)
    console.info(`获取:manifest.json的config.data的数据:${this.$app.$data.name}`)
    

    关于app与app.$def

    • 前者代表框架为开发者暴露提供的APP对象;后者代表开发者在app.ux中导出的对象,放置业务相关的全局数据和方法
    • 前者对象拥有onCreate, onDestroy生命周期;当应用启动时会执行onCreate方法,里面执行this.variable1的赋值是在$app对象上
    • 后者对象中的onCreate, onDestroy方法并不会执行,作用仅仅只是把方法复制到前者对象上而已
    • 这些全局方法在页面中:既可以通过this.$app.method1()调用,也可以通过this.$app.$def.method1()调用;不同之处在于前者可以取到之前赋值的variable1变量,而后者不可以取到(因为之前的赋值是在$app对象上执行的)

    3.2 页面生命周期

    image.png

    onInit()

    表示ViewModel的数据已经准备好,可以开始使用页面中的数据

    private: {
      // 生命周期的文本列表
      lcList: []
    },
    onInit () {
      this.$page.setTitleBar({ text: '生命周期' })
    
      this.lcList.push('onInit')
    
      console.info(`触发:onInit`)
      console.info(`执行:获取ViewModel的lcList属性:${this.lcList}`)   // 执行:获取ViewModel的lcList属性:onInit
      // $app信息
      console.info(`获取:manifest.json的config.data的数据:${this.$app.$data.name}`)
      console.info(`获取:APP文件中的数据:${this.$app.$def.data1.name}`)
      console.info(`执行:APP文件中的方法`, this.$app.$def.method1())
    }
    

    onReady()

    表示ViewModel的模板已经编译完成,可以开始获取DOM节点(如:this.$element(idxxx)

    onReady () {
      this.lcList.push('onReady')
    
      console.info(`触发:onReady`)
      console.info(`执行:获取模板节点:${this.$rootElement()}`)   // 执行:获取模板节点:<div attr={} style={"flexDirection":"column"}>...</div>
    }
    

    onShow(), onHide()

    页面被切换隐藏时调用onHide(),页面被切换重新显示时调用onShow()

    • 判断页面的显示状态,可以调用ViewModel$visible属性:true表示显示,false表示隐藏
    onShow () {
      this.lcList.push('onShow')
    
      console.info(`触发:onShow`)
      console.info(`执行:获取页面显示状态属性:${this.$visible}`)  // true
    },
    onHide () {
      this.lcList.push('onHide')
    
      console.info(`触发:onHide`)
      console.info(`执行:获取页面显示状态属性:${this.$visible}`)  // false
    }
    

    onDestroy()

    页面被销毁时调用,被销毁的可能原因有:用户从当前页面返回到上一页,或者用户打开了太多的页面,框架自动销毁掉部分页面,避免占用资源

    • 所以,页面销毁时应该做一些释放资源的操作,如:取消接口订阅监听geolocation.unsubscribe()
    onDestroy () {
      console.info(`触发:onDestroy`)
      console.info(`执行:页面要被销毁,销毁状态:${this.$valid},应该做取消接口订阅监听的操作: geolocation.unsubscribe()`)    // true,即将销毁
      setTimeout(function () {
        console.info(`执行:页面已被销毁,不会执行`)                // 页面已销毁,不会执行
      }.bind(this), 0)
    }
    

    onBackPress()

    当用户点击返回实体按键、左上角返回菜单、调用返回API时触发该事件

    • 如果事件响应方法最后返回true表示不返回,自己处理业务逻辑(完毕后开发者自行调用API返回);否则:不返回数据,或者返回其它数据:表示遵循系统逻辑:返回到上一页
    onBackPress () {
      console.info(`触发:onBackPress`)
    
      // true:表示自己处理;否则默认返回上一页
      // return true
    }
    

    返回上一页的接口API:router.back()

    onMenuPress()

    当使用原生的顶部标题栏时,可以通过manifest.json中的menu属性配置是否显示右上角的菜单

    onMenuPress () {
      this.lcList.push('onMenuPress')
    
      console.info(`触发:onMenuPress`)
    }
    

    A页面的生命周期接口的调用顺序

    • 打开页面A:onInit() -> onReady() -> onShow()
    • 在页面A打开页面B:onHide()
    • 从页面B返回页面A:onShow()
    • A页面返回:onBackPress() -> onHide() -> onDestroy()

    四、置顶对象

    • $app 应用对象
    • $app.$def 获取在app.ux中暴露的对象
    • $app.$data 获取在manifest.jsonconfig.data中声明的全局数据
    • $page 页面对象
    • $page.action 获取打开当前页面的action。仅在当前页面是通过filter匹配的方式打开时有效,否则为undefined。参见manifest
    • $page.uri 获取打开当前页面的uri。仅在当前页面是通过filter匹配的方式打开时有效,否则为undefined
    • $page.setTitleBar 设置页面标题
    • $valid 页面对象是否有效
    • $visible 页面是否处于用户可见状态

    this.$page.setTitleBar 参数属性包括

    {
      text: 'Hello QuickApp',        //标题栏文字
      textColor: '#ffff',            //文字颜色
      backgroundColor: '#434343',    //背景颜色
      backgroundOpacity: '0.8',      //背景透明度
      menu: false,      //是否在标题栏右上角显示菜单按钮 | 设置当前
    }
    

    五、全局对象

    • $element 获取指定id的组件dom对象,如果没有指定id,则返回根组件dom对象用法:this.$element('xxx')获取id为xxx的组件实例对象 this.$element() 获取根组件实例对象
    • $root 获取顶层ViewModel
    • $parent 获取父亲ViewModel
    • $child 获取指定id的自定义组件的ViewModel用法:this.$child('xxx') 获取idxxxdiv组件ViewModel
    • $vm(弃用) 请使用上面this.$child('xxx')`替代
    • $forceUpdate 强制页面刷新
    • $set 添加数据属性,必须在onInit函数中使用,用法:this.$set('key',value)
    • $delete 删除数据属性,如果在onInit函数中使用,用法:this.$delete('key')

    六、元素属性方法

    注意,获取元素应该在页面已渲染后,如 onReady 事件中或 onReady 事件执行完以后

    • $set 添加数据属性,用法:this.$vm('id').$set('key',value)
    • $delete删除数据属性,用法:this.$vm('id').$delete('key')
    • $on 在当前页面注册监听事件, 可监听$emit()$dispatch()$broadcast()等触发的自定义事件,不能用于注册组件节点的事件响应
    • $off 移除事件监听,参数 fnHandler 为可选,传递仅移除指定的响应函数,不传递则移除此事件的所有监听
    • $emit 触发当前实例监听事件函数,与 $on() 配合使用

    七、页面设计

    布局和尺寸

    • 采用border-box 模型且不支持 box-sizing 属性
    • 目前仅支持长度单位px%
    • 设计稿1px / 设计稿基准宽度 = 框架样式1px / 项目配置基准宽度(项目配置基准宽度:/src/manifest.jsonconfig.designWidth 的值,默认750)

    CSS

    • 可以使用内联样式、tag选择器、class选择器、id选择器来为组件设置样式
    • 仅可以使用并列选择、后代选择器、子代选择器
    • 支持@import引入外部样式、内联样式、行内样式
    • 颜色值不支持缩写,伪类支持不完全(支持:disabled,:checked,:focus等)

    八、组件

    <text><a><span><label>组件为文本容器组件,其它组件不能直接放置文本内容

    <div>: 和 HTML 一样

    支持样式 flex-direction, flex-wrap, justify-content, align-items, align-content

    <popup>: 气泡框

    • 支持属性 targetplacement
    • 支持样式 mask-color
    • 支持事件 visibilitychange
    • 自组件只能是<text>

    <refresh>: 下拉刷新

    • 支持属性 offsetrefreshing
    • 支持样式 background-colorprogress-color
    • 支持事件 refresh

    <richtext>: 富文本编辑器

    • 支持属性 type(值为 html)
    • 支持div样式, height 无效
    • 不支持子组件

    更多详情 https://doc.quickapp.cn/widgets/div.html

    九、页面切换和参数传递

    9.1 参数传递

    传递方法1

    <a>标签配合 queryString 传递参数, 这个和前端一致

    <a href="/src/home/index.html?key=2333">跳转页面</a>
    
    <!-- 添加变量参数 -->
    <a href="/PageParams/receiveparams?key={{title}}">携带参数key2跳转</a>
    

    传递方法2

    // 导入模块
    import router from '@system.router'
    

    通过 router 接口:router.push(), router.replace(), 接受一个如下结构的对象,用法这个和前端 router 一致。

    {
      url: '/src/home/index.html',
      params: { key: 2333 /* 需要传递的参数 */ }
    }
    

    接收参数

    上述2种传递参数的方法,其接收方法一致,在接收参数页面的 protected对象中获取即可(可设置默认值)

     export default {
        protected: {
          key: ''
        },
        onInit () {
          this.$page.setTitleBar({ text: '接收参数' })
    
          // js中输出页面传递的参数
          console.info('key: ' + this.key)
        }
      }
    

    回传参数

    开发者可能会遇到需要在页面之间回传参数的需求

    • 假设存在页面A和页面B,先从页面A跳转至页面B,然后从页面B返回到页面A时,需要传递参数
      = 此时,组件a和接口router传参不能满足需求,可以借助于app级别的对象:this.app.data

    页面A实现代码如下

    <template>
      <div class="tutorial-page">
        <a href="/PageParams/returnParams/pageb">跳转到页面B</a>
        <text>{{msg}}</text>
      </div>
    </template>
    
    <style>
      .tutorial-page {
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
      a {
        margin-top: 75px;
        font-size: 30px;
        color: #09ba07;
        text-decoration: underline;
      }
    </style>
    
    <script>
      export default {
        private: {
          msg: ''
        },
        onInit () {
          this.$page.setTitleBar({ text: '页面A' })
        },
        onShow () {
          // 页面被切换显示时,从数据中检查是否有页面B传递来的数据
          if (this.$app.$data.dataPageB && this.$app.$data.dataPageB.gotoPage === 'pageA') {
            // 从数据中获取回传给本页面的数据
            const data = this.$app.$data.dataPageB.params
            this.msg = data.msg
          }
        }
      }
    </script>
    

    页面B实现代码如下:

    <template>
      <div class="tutorial-page">
        <text>页面B</text>
        <input style="width: 450px;" placeholder="请输入回传给页面A的信息" onchange="updateMsg"/>
      </div>
    </template>
    
    <style>
      .tutorial-page {
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
    </style>
    
    <script>
      export default {
        private: {
          msg: ''
        },
        onInit () {
          this.$page.setTitleBar({ text: '页面B' })
        },
        onHide () {
          // 页面被切换隐藏时,将要传递的数据对象写入
          this.$app.$data.dataPageB = {
            gotoPage: 'pageA',
            params: {
              msg: this.msg
            }
          }
        },
        updateMsg (e) {
          // 更新input输入的信息文本
          this.msg = e.text
        }
      }
    </script>
    

    9.2 页面间通信

    https://doc.quickapp.cn/framework/script.html

    会利用到一个构造函数 new BroadcastChannel(string), 它接受一个字符串参数,作为实例的频道名称。它的实例具有以下属性和方法

    • name 频道名称,区分不同的消息频道(注意:不同频道之间不可通信)。
    • postMessage 用于在当前频道中广播消息
    • onmessage 订阅消息。在频道中接收到广播消息之后,会给所有订阅者派发消息事件
    • close 关闭当前的频道

    其中 onmessage 事件有2个属性(通过 event 对象访问)

    • type message
    • data 接收到的消息内容

    十、组件通信

    父组件到子组件

    • 子组件通过 props 获取父组件传入的值,见上文 template 部分
    • 通过 this.watch(props, callback) 监控传入数据变化并调用回调函数
    • 父组件通过this.$broadcast()完成事件触发,子组件通过$on()绑定事件并响应

    子组件到父组件

    • 父子组件传对象类型属于引用传递,可以直接修改父组件传入对象改变父组件数据
    • 子组件通过this.$dispatch()完成事件触发,父组件通过$on()绑定事件并响应
    • 子组件通过this.$emit()触发在节点上绑定的事件来执行父组件的方法
    • 注:this.$broadcast()this.$emit()this.$dispatch()参数一致
    • 注:触发时传递参数,再接收时使用event.detail来获取参数
    • 注:当传递结束后,可以调用event.stop()来结束传递

    十一、Deeplink

    配合<web>标签框架支持通过链接从外部打开应用,格式

    http://hapjs.org/app/<package>/[path][?key=value]
    https://hapjs.org/app/<package>/[path][?key=value]
    hap://app/<package>/[path][?key=value]
    
    • package: 应用包名,必选
    • path: 应用内页面的path,可选,默认为首页
    • key-value: 希望传给页面的参数,可选,可以有多个

    从传统网页调起需引入以下脚本

    <script src='//statres.quickapp.cn/quickapp/js/routerinline.min.js'/>
    

    十二、事件监听与触发

    $on 用于监听自定义事件;$off移除对应的事件监听

    $on(evtName, fnHandler)

    在当前页面注册监听事件, 可监听$emit()$dispatch()$broadcast()等触发的自定义事件,不能用于注册组件节点的事件响应

    export default {
        onInit(){
          this.$on('customEvtType1', this.customEvtType1Handler)
        },
        customEvtType1Handler(evt){
          // 事件类型,事件参数
          console.info(`触发事件:类型:${evt.type}, 参数: ${JSON.stringify(evt.detail)}`);
        }
      }
    

    $off(evtName, fnHandler)

    移除事件监听,参数 fnHandler 为可选,传递仅移除指定的响应函数,不传递则移除此事件的所有监听

    export default {
        removeEventHandler () {
          // 不传递fnHandler:移除所有监听
          this.$off('customEvtType1')
          // 传递fnHandler:移除指定的监听函数
          this.$off('customEvtType1', this.customEvtType1Handler)
        }
      }
    

    触发ViewModel事件

    页面的交互中可能会遇到一些非手动触发的需求,$emit() 通过触发当前实例上的事件达到动态触发事件的行为

    $emit(evtName, evtDetail)

    • 触发当前实例监听事件函数,与 $on() 配合使用
    • 注意:$emit() 目前只触发 $on 所监听的事件
    export default {
        emitEvent () {
          this.$emit('customEvtType1', { params: '参数内容' })
        }
      }
    

    监听原生组件事件

    • 原生组件支持一系列事件,如通用事件(如:click, disappear)、组件专有事件(如:focus)
    • 在响应函数执行时通过target获取,如:onClickHandler
    • 在响应函数绑定时传递参数,如:onClickHandler2
    <template>
      <div class="tutorial-page">
        <text id="elNode1" class="{{ elClassName + 1 }}" disabled="false" onclick="onClickHandler">组件节点1</text>
        <text id="elNode2" class="class-static-1 {{ elClassName + 2 }}" onclick="onClickHandler2('参数1', argName)">组件节点2</text>
      </div>
    </template>
    
    <style lang="less">
      .tutorial-page {
        flex-direction: column;
      }
    </style>
    
    <script>
      export default {
        private: {
          elClassName: 'class-dynamic',
          argName: '动态参数'
        },
        onClickHandler (evt) {
          // 事件类型,参数详情
          console.info(`触发事件:类型:${evt.type}, 详情: ${JSON.stringify(evt.detail)}`);
    
          if (evt.target) {
            console.info(`触发事件:节点:${evt.target.id}, ${evt.target.attr.disabled}`)
          }
        },
        onClickHandler2 (arg1, arg2, evt) {
          // 事件类型,事件参数,target
          console.info(`触发事件:类型:${evt.type}, 参数: ${arg1}, ${arg2}`);
        }
      }
    </script>
    

    触发原生组件事件

    通过$emitElement()完成事件的动态触发

    • $emitElement(evtName, evtDetail, id)

    可以触发指定组件id的事件,通过evt.detail获取传递的参数;该方法对自定义组件无效

    <template>
      <div class="tutorial-page">
        <text onclick="emitElement">触发组件节点的事件:click</text>
        <text id="elNode1" class="{{ elClassName + 1 }}" disabled="false" onclick="onClickHandler">组件节点1</text>
        <text id="elNode2" class="class-static-1 {{ elClassName + 2 }}" onclick="onClickHandler2('参数1', argName)">组件节点2</text>
      </div>
    </template>
    
    <style lang="less">
      .tutorial-page {
        flex-direction: column;
      }
    </style>
    
    <script>
      export default {
        private: {
          elClassName: 'class-dynamic',
          argName: '动态参数'
        },
        onClickHandler (evt) {
          // 事件类型,参数详情
          console.info(`触发事件:类型:${evt.type}, 详情: ${JSON.stringify(evt.detail)}`);
    
          if (evt.target) {
            console.info(`触发事件:节点:${evt.target.id}, ${evt.target.attr.disabled}`)
          }
        },
        onClickHandler2 (arg1, arg2, evt) {
          // 事件类型,事件参数,target
          console.info(`触发事件:类型:${evt.type}, 参数: ${arg1}, ${arg2}`);
        },
        emitElement () {
          // 注意:通过此类方式的事件不会携带target属性,开发者可以通过detail参数实现
          this.$emitElement('click', { params: '参数内容' }, 'elNode1')
        }
      }
    </script>
    

    十三、打包及发布

    13.1 编译工具

    1)编译打包工程

    • 在工程的根目录下运行
    npm run build
    
    • 编译后的工程目录在/build
    • 生成的应用路径为/dist/.rpk

    2)增加 release 签名

    通过 openssl 命令等工具生成签名文件private.pemcertificate.pem,例如:

    https://doc.quickapp.cn/tools/compiling-tools.html

    opensslreq -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 3650 -outcertificate.pem
    

    在工程的 sign 目录下创建 release 目录,将私钥文件 private.pem 和证书文件 certificate.pem 拷贝进去

    3)发布程序包

    发布程序包前需要增加release签名,然后在工程的根目录下运行

    npm run release
    
    • 生成的应用路径为/dist/.release.rpk
    • 如果需要临时使用 debug 签名,可以使用
    npm run release -- --debug
    

    13.2 IDE发布

    • 1)生成证书。点击快应用面板的【生成证书】按钮, 按提示输入相关信息
    • 2)生成发布用 RPK。点击【发布 rpk包】按钮, 生成成功的话会弹出对应的文件夹

    image

    十四、快应用分享专题

    image

    十五、上传到快应用中心审核

    快应用注册账号 https://www.quickapp.cn/docCenter/post/74

    image.png

    十六、一些问题

    • 资源文件、代码文件的命名均不能含有中文,命名不能连续使用下划线,否则打包发布时会包解析失败,导致无法上传
    • 自定义属性名不能采用驼峰命名,否则值永远是 undefined
    • show 属性并不好用,没起什么作用
    • 类似 onInit 等等函数是页面生命周期,不是组件生命周期,不会因为组件状态变化而执行
    • display类型只有 flexnone
    • 子盒子不能将父盒子撑高
    • 不遵循盒子模型,类似但不完全等同于 border-box
    • 不能全局引用样式,只能在每个page中使用@import引入
    • <block>逻辑控制块,仅支持forif/elif/else,不支持show条件渲染
    • justify-content属性,在快应用官方开发环境中,目前不支持space-around
    • 针对于目前vscode插件hap-extension不支持sass语法,可以把.scss单独存储,通过style.src引入到.ux中,同时方便管理
    • 当前自定义组件不支持传入的propsfunction
    • 快应用中很多 html都不能用,比如没有 p,h1~h2 等,因为它只是模拟了部分 html标签,最终会转化成原生组件
    • 只能使用 aspantextlabel 放置文本内容
    • position 只能是 fixednone
    • 长度单位只有 px%

    十七、快应用开发资源

    官方资讯

    官方文档

    工具

    示例

    插件

    教程

    讨论

    分享



    作者:poetries
    链接:https://www.jianshu.com/p/94fc14897c9f
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • H5应用转换快应用

    千次阅读 2022-01-10 15:42:56
    1.H5应用及快应用介绍 H5应用 第五代Html标准开发的web应用,浏览器通过解析HTML,就可以把网页内容显示出来; 跨平台性; 浏览器上运行。 快应用 提供原生体验的免安装应用; 行业标准,现在有超过12家智能...
  • 集微网4月7日消息(文/数码控),近日小米官方放出了MIUI负责人在线关于快递类型短信的优化、快应用的用途等大家关心的问题的解答汇总,一起来看看吧!问:短信验证码来的时候,弹出时可以出个“复制并删除”按钮吗?...
  • 快应用之授权登录

    千次阅读 2019-10-17 17:50:26
    先要在华为快应用网站上先创建一个快应用,这个快应用的名字等信息要和你即将要开发的快应用名字一样 获取appid方法的链接 证书指纹必须在华为ide上才能获取 获取授权的接口文档也应该查看华为的开发文档,并...
  • 华为帐号是用户访问华为云业务的凭证,拥有华为帐号的用户,可以使用华为云业务,如华为云服务、华为游戏中心、华为应用市场等。 华为帐号的开放基于OAuth2.0协议标准,在获得用户授权后,应用...阅读类的快应用通过获
  • 快应用开发工具黑屏解决方案

    千次阅读 2022-03-04 10:40:49
    博主用ide 的新建模板功能新建了一个快应用图书模版 的快应用,其实模板文件新建一半博主电脑卡主了,然后就关掉了 开发工具,导致再次打开开发工具后就变这样了。(因为下次打开会优先打开上传关闭时的快应用,而...
  • 写在前面 在去年的开发者大赛征文中,我们通过多个社区联合活动收集了很多优质文章...从今天起,我们会陆续把一些优秀文章推送出来,希望帮助大家更好的开发快应用。 本期作者:执着的烙印 因为文章内容较多,...
  • 上篇作者为大家讲了什么是快应用以及快应用的开发流程,这期作者分享了快应用开发中遇到的问题和解决办法,一起来看看吧! 说起快应用,不得不说快应用踩过的坑。 快应用还处于不断优化阶段,在开发过程中,也...
  • 3月20日,小米、中兴、华为、金立、联想、魅族、努比亚、OPPO、vivo、一加,共十家手机厂商在北京联合召开快应用标准启动发布会,手机厂商与中国信息通信研究院、电信终端产业协会、中国软件行业协会及数百家知名...
  • 快应用App开发

    千次阅读 2018-06-11 17:13:38
    快应用是基于手机硬件平台的新型应用形态,标准是由主流手机厂商组成的快应用联盟联合制定,它具备传统APP完整的应用体验,无需安装、即点即用。集合了Vue和小程序的特点。虽然有人说,快应用只是雷声大,雨点小,...
  • 快应用 九大厂商同时宣布建立即时应用生态发展联盟,通过统一标准让开发者低成本接入,“快应用”在研发接口、场景接入、服务能力和接入方式上建设标准平台,以平台化的生态模式对个人开发者和企业开发者全品类开放...
  • 华为快应用接入广告服务开发指导

    千次阅读 2022-01-21 22:40:41
    华为广告变现服务是依托华为终端强大的平台与数据能力为开发者提供的应用流量变现服务,开发者通过该服务可以在自己的应用中获取并向用户展示精准的、精美的、高价值的广告内容,并从中获得广告收益。 高额变现收益 ...
  •  根据小米、魅族、vivo等方面的官宣消息,3月20日,9大主流手机厂商将共同启动「快应用」标准,打造移动应用新生态,目标直指急速扩张中的微信小程序。 快应用是什么? 继2017年小米推出「直达服务」、魅族推出「...
  • 最新遇到一个需要从快应用跳转到Android App的需求,以下记录下实现的方式。 在需要跳转的目标安卓App的activity中添加对外的schema,示例代码如下: <activity android:label="@7F070043" android:name=...
  • Android快应用开发(一)

    千次阅读 2019-08-12 16:24:06
    快应用是Android未来的使用趋势,其优势在于免安装,渲染能力强,使用原生系统的能力强,H5实时更新等。 在华为2019的开发者大会中也是吹了一把快应用,快服务的使用,以后在鸿蒙系统中也会支持这种快速开发,高效...
  • 安卓手机如何永久关闭快应用

    万次阅读 2021-12-07 10:05:54
    三步让你永久关闭安卓手机快应用,告别流氓软件
  • 手把手教你接入快应用Push

    千次阅读 2020-10-20 15:04:49
    越来越多的CP在AGC上上架了快应用之后,希望吸引越多的用户,提高应用的活跃度,从而带来更多的流量,最终实现他们的商业价值。快应用提供了标准的Push能力,开发者可以给用户推送消息,比如推送一本好书、推送一个...
  • 快应用开发详解

    万次阅读 2018-03-22 15:20:31
    1. 快应用是基于手机硬件平台的新型应用形态,标准是由主流手机厂商组成的快应用联盟联合制定。 2. 快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台,以平台化的生态模式对个人开发者和企业...
  • 我们都会有手机内存不够用的时候,app太过于能占内存,而快应用却恰好,占内存恨少。 我们每个人的手机都会安装各类的应用,然而传统的应用都需要下载安装后才可以使用。 然而,华为手机提供快应用功能,无需安装...
  • 快应用开发教程【01】--环境与调试

    千次阅读 2019-02-16 09:36:44
    接下来我们就可以开发我们的快应用了。 一、环境搭建 1、安装NodeJs ⚠️:安装6.0以上版本的NodeJS,推荐v6.11.3。不要使用8.0.*版本.这个版本内部ZipStream实现与node-archive包不兼容,会引起报错 官网...
  • 开发者将快应用上架应用市场后,希望能有多个入口直达快应用,从而提高其快应用的曝光率,带来更多的流量。而快应用开放的标准deeplink能力可以满足开发者的需求。 应用场景 Deeplink可以应用在如下场景: 社交分享...
  • · 精准搜索:打开全局搜索-搜索对应的快应用名称-秒开,例如京东 · 内容搜索、泛搜索:打开全局搜索-搜索内容-秒开,例如小说 · 关键词搜索:搜索唯品会、淘票票 2、 负一屏 · 桌面滑动到最左一屏—点击...
  • 华为快应用IDE是一款针对快应用及快服务卡片开发的集成开发环境,它以DevOps理念为开发者提供了全流程开发解决方案,实现快应用和快服务卡片的快速交付。下载地址:...
  • 快应用和卡片都是通过router.push接口来跳转其他快应用的,使用Deeplink中的hap链接来实现的,同时hap链接里是可以携带参数,在跳过去时加个flag参数,在B快应用的B1页面获取参数,根据参数值判断来源是负一屏的卡片...
  • 快应用环境配置

    千次阅读 2018-03-22 13:56:00
    早上看到一个新闻,十大手机厂商联手推出“快应用”,据说是为了对抗小程序的。不得不感叹,这互联网发展速度实在是太快了,选择进入程序员这个行业,只能说,不学习就要被淘汰了。 先是原生的安卓和ios,当时原生...
  • 快应用规范从1070版本开始强制设置显示菜单,但是在有些快应用页面,菜单会遮挡住应用自身的内容,例如下图菜单便遮挡住了登录功能,虽然可以将菜单配置为可移动,但是用户却不知道可以移动,从而影响用户的使用。...
  • 文章来源于快应用官方论坛-本文作者“xiaoTian” 一、场景 笔者在之前快应用开发过程中,发现除了快应用自身的开发之外,还存在使用H5来唤醒快应用的情况,目的是一方面为了给可支持快应用的用户提供...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,825,442
精华内容 1,130,176
关键字:

快应用

友情链接: 1187138.rar