快应用官网
快应用教程
从上述可以看出 快应用的覆盖面比较窄,仅支持10种手机型号,像iPhone、三星等都是不支持快应用的~。但是快应用的优势还是比较明确的无需安装、即点即用,用完即走,简单来说就是比较方便,可以提升用户体验度。用户可以在 URL 链接、全局搜索、应用商店、浏览器、负一屏、系统桌面、PUSH、语音助手、安全中心、垃圾清理、信息助手、天气、短信模板、日历、个性主题、文件管理等等任何地方作为入口打开快应用…
开发快应用的前提就是安装快应用开发工具
第一次打开时显示为英文是因为配置还没有加载好,关闭之后重新打开显示的就是中文了。
新建工程界面展示如上,可以选择快应用、快应用卡片、 快应用(Webview) 三类项目
选择某一模版,点击下一步,项目创建完成。
如果您基于官方模版,创建新项目,需要先安装依赖,才能正常运行。您可以使用 yarn 或 npm i 命令,在终端运行来安装依赖,然后运行项目。
也可点击下图的 安装依赖,重新启动编译来启动项目(其实就是快捷键)。
在开发过程中,快应用运行效果,会在主界面右侧的模拟器中显示。
但是模拟器中运行的效果和真机存在差异
因此实际开发过程中还需要使用真机来预览,来调试快应用的实际运行情况。
前提:准备一台安卓手机,确保手机处于开发者模式
若是不确定手机是否处于开发者模式: 设置 -> 关于手机 -> 软件版本 -> 多次点击软件版本号至提示“您已处于开发者模式,无需进行此项操纵”为止
步骤
[1] 使用数据线连接电脑与手机
确保数据线可以传输数据而不是只能用于充电;否则会报错–> 找不到Android
[2] 点击 IDE 工具栏的「USB 调试」开始调试
每次运行调试时,开发者工具会检测您的手机是否安装了【快应用预览版】【快应用调试器】。如果未安装,开发者工具将自动安装。 若是已安装会自动打开快应用预览版进入快应用首页进行调试,与此同时电脑端会打开调试页面。
打包: 点击顶部工具栏的打包按钮
若无签名,会索引您添加签名
点击完成之后会自动在项目根目录生成一个sign
文件里面存储签名。
若是存在签名:快应用开发工具将自动生成 release 签名的包,既可以直接使用rpk包上传至官网也可上传包管理平台,如下:
包管理平台: 在打包完成之后可以点击上传包管理平台上传本次rpk文件,上传成功之后会出现一个二维码和包管理平台的链接,您可使用调试器的扫码功能,打开此快应用
上传至官网:在开发完成之后,若您想发布上线该快应用,可以通过快应用开发工具的「上传」功能,将其上传至官网的开发者中心,后续可在官网按照流程填写相关信息后,发布上线快应用(当然,您也可以在后台,手动提交 RPK 包)
问题: 在更新版本上传rpk文件时,提示版本号必须高于上一个版本
。
原因:出现这个问题的原因是快应用官方以配置 manifest.json 的属性versionCode
的值来确认版本更新,官方要求每次上架更新需要将该值手动 自增1。很多同学会误以为修改 versionName 来更新版本,versionName 应该是属于那种显示在应用商店的版本号!
我就是在版本迭代时只是修改了versionName属性值但是没有修改versionCode属性的值,因此在发布时一直提示“版本号必须高于上一个版本”。
现在回想一下Vue页面构成
ux文件与vue文件结构完全相同,但是语法有所区别
不支持原生HTML
,开发快应用只能使用快应用组件和基于快应用组件封装的组件;存在很多样式兼容问题
,需要后面一一记录
兼容性问题产生的原因是:每个快应用组件支持的样式不一样,我们如果一直按照使用原生HTML的思维去使用快应用组件,就会感觉某些样式不起作用了,就会感觉存在某些兼容性问题!
在快应用中不支持使用原生html —> 若是使用原生html直接不显示!
因此在开发快应用时只能使用快应用组件~比如div、text…
此时需要注意的是:这些组件不是原生html标签,在使用时需要关注组件支持的样式、事件以及是否能存放文本
!
举例说明
常用的快应用组件
在pages
中定义的组件被称为页面级组件。
页面级组件(等同于Vue页面),通过路由配置可以进行页面跳转。
在components
中定义的组件被称为自定义组件。
自定义组件(等同于Vue的子组件),将使用比较多的部分进行封装,可以多次使用。
父组件给子组件传值使用的是props,其语法与vue 的props传值类似,可以规定传值类型、默认值等,还可以进行数据校验。
区别: 父组件给子组件进行传值时使用的是短横线分割命名,在子组件中通过props 接收时使用的是驼峰命名
在进行校验时,验证顺序是 必填项检查 -> 类型检查 -> 函数检查
语法
<!-- 如果属性名是多个单词 使用短横线分割命名 -->
<son 属性名=属性值></son>
props: [] // 仅类型检查
props:{
属性名:{
type: String/Number... // 类型检查
required: true/false // 是否必填
default: // 默认值
validator: function(value){
return true/false // 检查是否符合要求
}
}
}
举例说明:在父组件接收三个参数分别为name( 字符串类型且必传),年龄(数字类型,只能接受18,19,29三个中的某一个数字),地址(字符串类型,不能超过18个字, 默认为中国)并将展示在页面上
父组件
<import name="son" src="../../components/Detail"></import>
<template>
<div class="wrapper">
<son per-name='{{name}}' per-age='{{age}}'></son>
</div>
</template>
<script>
export default {
public:{
name: 'chaochao',
age: 18
}
}
</script>
子组件
<template>
<div class="wrapper">
<text>{{ perName }}</text>
<text>{{ perAge }}</text>
<text>{{ perArea }}</text>
</div>
</template>
<script>
export default {
props:{
perName:{
type: String,
required: true
},
perAge:{
type: Number,
validator: function(value){
return [18, 19, 29].includes(value)
}
},
perArea:{
type: String,
default: '中国',
validator: function(value){
return value.length < 18
}
}
}
}
</script>
父给子组件进行传值是单向数据流,也就是说子组件不能直接修改父组件传值的引用!
语法
// 子组件
this.$dispatch('子组件触发事件名',值)
// 父组件
onInit(){
this.$on('子组件触发事件名',触发的父方法方法)
}
// 子组件
this.$emit(方法名,值)
// 父组件
<son on方法名=‘父组件方法’></son>
举例说明:在子组件修改父组件传过来的name属性
方式1
方式2
tips: 当传递结束后,可以调用value.
stop()
来结束传递,否则会一直传递下去
<son id='xxx'>son>
const ele = this.$child('子组件id名') // 获取子组件
ele.方法名() // 方法调用
相对于组件的生命周期来说自定义组件的生命周期并不全,仅有3个生命周期函数。
如上:自定义组件只有3个三个生命周期函数
在使用时需要注意时机。
父组件init -> 子组件init -> 子组件ready -> 父组件ready -> 父组件show
this指向的是vm实例化对象(使用与vue2.x中相同)
定义数据时:页面级组件定义数据时可以根据需要将数据定义在data、public、protected、private属性中(data不可与public、protected、private同时存在)
自定义组件中数据模型只能
使用data 属性
无论是定义在data、public、protected、private、props中定义的变量,都会平铺在实例化对象身上,在script中可以直接通过this.属性名
去使用,在template模版中通过{{}}
去使用。
函数和配置项在同一级别!声明的函数会直接平铺在实例化对象身上,在script中可以直接通过this.方法名
去使用,在template模版中通过{{}}
去使用。
在快应用中不能使用BOM、DOM,因此也不能使用window作为全局对象。
在快应用中global对象可以直接使用,我们可以将封装的公共方法添加在global对象上(类似于将封装的公共方法添加在vue实例化对象上)。
)。
在快应用上进行事件绑定与vue2.x中相同(唯一的区别是在vue2.x中是将方法定义在methods配置项中,定义在methods配置项中的方法会被平铺在实例化对象上;而快应用中是直接将定义的方法平铺在实例化对象上–不定义在methods配置项中)
列表渲染-for循环
t条件渲染-if与show
计算属性的使用与vue2.x中相同。
官网
在快应用中可以通过 a组件
(类似vue中的link组件)进行声明式导航,不仅可以跳转到站内页面、还可以通过webView加载网页、掉起电话、短信、邮件…
<template>
<div class="wrapper">
<a href="/pages/Home">去首页1a>
<a href="pages/Home">去首页2a>
<a href="tel:10086">打电话a>
<a href="sms:10086">发短信a>
<a href="mailto:[email protected]">发邮件a>
<a href="https://www.baidu.com/">打开webView加载网页a>
div>
template>
在快应用中是通过router接口进行路由跳转的(类似vue中的router)
router接口提供一下几个方法进行路由跳转
router.push
方法
router.push(OBJECT)支持的参数 uri 与组件 a 的 href 属性完全一致
router.replace
方法
router.replace(OBJECT)的支持的参数 uri 不支持调起电话、短信、邮件,其他与 push 一致
router.back方法返回上一级
router.clear方法清空历史记录仅保留当前页面
<template>
<div class="wrapper">
<text @click='jump(1)'>去首页1</text>
<text @click='jump(2)'>去首页2</text>
<text @click='jump(3)'>打电话</text>
<text @click='jump(4)'>发短信</text>
<text @click='jump(5)'>发邮件</text>
<text @click='jump(6)'>打开webView加载网页</text>
</div>
</template>
<script>
import router from '@system.router'
export default {
jump(type){
let uri =''
switch(type){
case 1:
uri = '/pages/Home'
break;
case 2:
uri = 'pages/Home'
break;
case 3:
uri = 'tel:10086'
break;
case 4:
uri = 'sms:10086'
break;
case 5:
uri = 'mailto:[email protected]'
break;
case 6:
uri = 'https://www.baidu.com/'
break;
}
router.push({
uri
})
}
}
</script>
使用a组件或router接口进行路由跳转时----传递参数与接收参数方式一致。
<a src='xxx?key1=value1&key2=value2'>路由跳转</a>
router.push({uri:'xxx?key1=value1&key2=value2'})
router.push({
uri: 'xxx',
params:{
key1: value1,
key2: value2
}
})
jump(type){
router.push({
uri: '/pages/Home',
params: { value: 222222 }
})
}
public或protected
中定义key名相同
的属性,否则接收不到!onReady() {
console.log(this.value) // 不先定义接收不到undefined
}
public:{
value: ''
},
onReady() {
console.log(this.value) // 222222
}
protected 内定义的属性,允许被应用内部页面请求传递的数据覆盖,不允许被应用外部请求传递的数据覆盖
可以通过在 app.ux 中增加缓存的数据,并提供读写缓存数据的能力来实现。
封装缓存数据方法
页面启动模式
页面的启动模式有两种,可以通过manifest.json配置文件的 router.page.launchMode
进行配置
standard(默认):每次打开新的目标页面(页面栈中会存在相同的目标页面)
singleTask:每次打开目标页面都会检查页面栈中是否存在目标页面:
若是存在[1]清除页面栈中该页面上
打开的其他页面[2]打开已有的目标页面并回调 onRefresh 生命周期函数;
若是不存在则创建新的目标页面实例并打开
只看上面解释会比较模糊,举例说明: 现在有A、B、C三个页面,页面的启动模式如下
"pages/A": {
"launchMode": "singleTask",
"component": "index"
},
"pages/B": {
"launchMode": "standard",
"component": "index"
},
"pages/C": {
"launchMode": "singleTask",
"component": "index"
}
现在使用router.push(左上角返回会有所不同哦)依次打开页面PageA -> PageB -> PageC -> PageB -> PageC -> PageA
下面结合生命周期进行说明
[1]PageA:当前页面栈为空,创建A页面并打开
-----A页面生命周期------
onInit
onShow
此时页面栈: PageA
[2]PageB: PageB的启动模式为standard(每次打开新的页面), 创建B页面并打开
-----A页面生命周期------
onHide
-----B页面生命周期------
onInit
onShow
此时页面栈: PageA, PageB
[3]PageC:PageC的启动模式为singleTask,此时C页面为首次打开,创建C页面并打开
-----B页面生命周期------
onHide
-----C页面生命周期------
onInit
onShow
此时页面栈: PageA, PageB, PageC
[4] PageB: PageB的启动模式为standard(每次打开新的页面), 创建B页面并打开
-----C页面生命周期------
onHide
-----B页面生命周期------
onInit
onShow
此时页面栈: PageA, PageB, PageC, PageB
[5]PageC:PageC的启动模式为singleTask,找到页面栈中PageC,销毁PageC前面的页面即PageB
-----B页面生命周期------
onHide
onDestory
-----C页面生命周期------
onShow
onRefresh
此时页面栈: PageA, PageB, PageC
[6]PageA:PageA的启动模式为singleTask,找到页面栈中PageA,销毁PageA前面的页面即PageB与PageC
-----C页面生命周期------
onHide
onDestory
-----C页面生命周期------
onDestory
-----A页面生命周期------
onShow
onRefresh
此时页面栈: PageA
若是页面栈中存在大于1个页面,则在页面左上角存在返回按钮。
点击返回按钮,会销毁当前页面
并打开上一级页面。
举例说明
现在存在页面Demo(首页), Home页面
----Demo生命周期----
onInit
onShow
----Demo生命周期----
onHide
----Home生命周期----
onInit
onShow
----Home生命周期----
onHide
onDestory
----Home生命周期----
onShow(不会走onRefresh)
App的生命周期在app.ux
中定义的回调函数。
onCreate() {
prompt.showToast({
message: 'onCreate--应用调用--onCreate'
})
},
onRequest(){
prompt.showToast({
message: 'onRequest--监听应用收到一个外部的打开新页面的请求--onRquest'
})
},
onShow(){
prompt.showToast({
message: 'onShow--应用返回前台时调用--onShow'
})
},
onHide(){
prompt.showToast({
message: 'onHide--应用退到后台时调用--onHide'
})
},
onDestroy(){
prompt.showToast({
message: 'onDestroy--应用销毁时调用--onDestroy'
})
},
onError({message}){
prompt.showToast({
message: 'onError--应用报错时调用--onError'+`错误原因是${message}`
})
}
上述代码
[1] 您可以在app.ux的< script >中引入一些公共的脚本,并暴露在当前 app 的对象上,然后就可以在页面 ux 文件的 ViewModel 中,通过this.$app.$def.xxx
访问,如下
// 公共方法文件
export default {...}
//app.ux文件
<script>
//import utils from './helper/utils'
const utils = require('./helper/utils').default
export default{
utils
}
</script>
// 其他ux页面
this.$app.$def.utils // 可以获取到处的公共对象
[2] 另外一些公用方法也可以直接声明在app.ux中
,这些方法也可以通过this.$app. $def.方法名去使用, 也可以通过 this. $app.方法名
直接使用!
[3] 在app.ux中定义的数据如下
data:{
text: 111
}
也可以通过this.$data. $def.data.text, 此时获取的值为111。
//获取 app 缓存的数据
getAppCache (key) {
return this.dataCache ? (this.dataCache[key] || '') : ''
},
// 设置 app 缓存的数据
setAppCache (key, val) {
if (val === '' && this.dataCache[key]) {
delete this.dataCache[key]
return
}
this.dataCache[key] = val
},
clearAppCache () {
this.dataCache = {}
}
使用直接通过$app去使用即可。
this.$app.setAppData()
在实际开发过程中,若是存在一些常量且在项目的多个地方使用时,可以将该数据存储在manifest.json
配置项的config.data
中。
在使用时可以通过$app.$data
去获取。
this.$app.exit() // 退出开应用,结束应用生命周期
manifest配置文件1-配置信息
manifest配置文件2
应用包名,是区别于其他应用的唯一标识。
推荐采用 com.company.module 的格式,示例如下:
{
"package": "com.example.demo"
}
应用名称,6 个汉字以内,与应用商店保存的名称一致;框架提供保存到桌面的功能,桌面上显示的应用名即为此属性;示例如下:
{
"name": "发票小助手"
}
规则为正方形(不能是圆角),且务必无白边;
{
"icon": "/assets/images/logo.png"
}
在上传时显示的图标img即为此处的图标。
应用版本名称、版本号为开发者的应用包维护的版本信息;
应用版本名称为主版本.次版本格式;
应用版本号为整数,从 1 开始,每次更新上架请自增 1;
示例如下:
{
"versionName": "1.0",
"versionCode": 1
}
在上传时版本以versionCode为准,在应用商店展示的版本号以versionName为准
router,路由,用于定义页面的实际地址、跳转地址。如果 ux 页面没有配置路由,则不参与项目编译。一个目录下最多只能存在一个主页面文件(不包括组件文件)。
"router":{
"entry": "首页页面目录名"
}
"router":{
"pages": {
"页面目录名": {
"component": "与 ux 文件名保持一致"
}
}
}
注意事项
[1] 一个目录下最多只能存在一个主页面文件(不包括组件文件)
src
— pages
— Test
— test.ux
— test2.ux
如上文件在Test中存在 test.ux、test2.ux两个ux文件,但是这两个文件不能都作为主页面文件,因为一个目录下最多只能存在一个主页面文件!
"router":{
"pages/Test": {
"component": "test",
"path": "/test1"
},
"pages/Test": {
"component": "test2",
"path": "/test2"
}
}
此时会报错 Duplicate object key(重复配置)
若是想给这两个文件设置路由
src
— pages
— Test
— test.ux
— test2
— test2.ux
"router":{
"pages/Test": {
"component": "test",
"path": "/test1"
},
"pages/Test/Test2": {
"component": "test2",
"path": "/test2"
}
}
请在 页面切换->页面切换模式 目录下查看
display用于设置UI 显示相关的配置。
"display": {
"statusBarBackgroundColor": "#FFEBF1" // 状态栏背景色,默认值同标题栏背景色
}
tips: 状态栏的背景不能设置渐变色 且 状态栏不可隐藏!
"display": {
"titleBar": true, //是否显示titleBar
"titleBarBackgroundColor": "#f00000", // 全局titleBar背景色
"titleBarTextColor": "#ffffff", // 全局titleBar的title文本颜色
"titleBarText": "快应用", // 全局titleBar的title文本内容
"pages": { // 页面私有UI显示,不设置默认使用全局配置
"pages/DemoDetail": {
"titleBarText": "详情页"
}
}
}
如上图想在titleBar想做一个背景渐变色,于是进行如下设置
"display": {
"titleBar": true, //是否显示titleBar
"titleBarBackgroundColor": "linear-gradient(78deg, #FFEBF1 0%, #FEF2F4 48%, #E1EDFF 100%);", // 全局titleBar背景色
}
发现背景颜色显示的是黑色(默认值),说明titleBarBackgroundColor配置项不支持渐变色格式的颜色。
那如果想做渐变色应该如何设置呢?
可以通过titleBar: false关闭配置项的titleBar,在页面上添加一个titleBar的组件!
titleBar的标题默认居左且不支持修改,若是想要标题居中需要使用自定义tabBar;
"display": {
// 此处配置为全局页面配置,若是想进行私有配置---> 在pages中进行配置!
"menuBarData": {
"menu": true, //是否显示MenuBar(1000-1060)
"menuBar": true, //是否显示MenuBar(1070+)
"shareTitle": "测试分享标题", // 分享标题
"shareDescription": "测试描述测试描述测试描述测试描述测试描述测试描述测试描述测试描述测试描述测试描述", // 分享秒杀
"shareIcon": "/assets/images/shareIcon.png", // 分享展示图标
"shareParams":{”channel“: “default”}, // 分享携带参数(是否能成功接收未验证)
"usePageParams": true // 是否携带当前页面的参数
},
"pages": {
"pages/Demo": { }
}
}
此处先熟悉manifest.json配置文件router配置项的
launchMode
配置项-页面启动模式
web页面开发:在浏览器页签中每次只能有一个页面,当前页签打开另一个页面,上个页面就销毁了;
在浏览器页签打开某个页面1(页面1初始化、渲染…),在当前页签打开页面B(页面1销毁,页面2初始化、渲染…)
快应用开发:可以同时运行多个页面,但是每次只显示其中一个页面。
页面栈中就是存储当前打开的页面!
生命周期
生命周期 | 概括 | 等价vue中的哪个周期 |
---|---|---|
onInit | 数据已经准备好,可以开始使用页面中的数据 | created |
onReady | 模板已经编译完成,可以获取dom节点 | mounted |
onShow | 页面重新显示时调用 | |
onHide | 页面被隐藏时调用 | |
onDestory | 页面被销毁时调用 | beforeDestory |
此处先熟悉manifest.json配置项中的display配置项配置。
踩坑
在Home页面监听onMenuPress事件无反应!
// 点击menuBar按钮时onMenuPress函数根本没有被调用!
onMenuPress(){
prompt.showToast({
message: '111111'
})
return true
}
原因是manifest.json配置文件的display
配置项的menu
属性没有设置为true!
"display": {
"menu": true,
"titleBar": true // 兼容1070之前
}
此时点击右上角不会拉起分享弹窗并提示111111
函数的执行时机
singleTask
时,仅会存在一个目标页面实例,用户多次
打开目标页面时触发此函数。flag 'clearTask'
,且页面实例已经存在
时触发详情请在 页面切换->页面切换模式 目录下查看
语法
// 该回调中参数为重新打开该页面时携带的参数
onRefresh(query) {
console.log('page refreshed!!!')
}
注意: launchMode 为 singleTask 时,重新打开页面时携带的参数不会自动更新到页面 this 对象上
,需要在此处从 query 中拿到并手动更新
。
onPageScroll(evt) {
console.log(`页面滚动距离:${evt.scrollTop}`)
}
onReachTop(){
// 页面触顶时触发
}
onReachTop(){
// 页面触底时触发
}
通用方法,即提供给所有组件调用的方法。
获取指定 id 的组件 dom 对象,如果没有指定 id,则返回根组件 dom 对象用法。
this.$element('id名')
const element = this.$element('元素id名')
element.getBoundingClientRect({
success: data =>{
// data中包含元素的宽高 ,left\right\bottom\top
}
})
在项目中使用到的接口都需要在配置文件manifest.json中声明,不然会报如下警告
[WARN] 请在 manifest.json 文件里声明项目代码中用到的接口: system.storage, service.account, system.package, system.webview
system.package
的hasInstalled方法"features": [
{
"name": "system.package"
},
]
import pkg from '@system.package'
pkg.hasInstalled({
package: 'app包名',
success: function(data) {
console.log(`handling success: ${data.result}`)
// result为true表示app已安装
// result为false表示app未安装
},
fail: function(data, code) {
console.log(`handling fail, code = ${code}`)
}
})
system.package
的install方法"features": [
{
"name": "system.package"
},
]
import pkg from '@system.package'
pkg.install({
package: '应用包名',
success: function(data) {
console.log(`handling success: ${data.result}`)
// result:true 下载成功
// result: false 下载失败
},
fail: function(data, code) {
console.log(`handling fail, code = ${code}`)
}
})
system.shortcut
的hasInstalled方法"features": [
{
"name": "system.shortcut"
},
]
import shortcut from '@system.shortcut'
shortcut.hasInstalled({
success: function(res) {
// res 为true表示已创建图标
// res weifalse表示未创建图标
}
})
system.shortcut
的install方法"features": [
{
"name": "system.shortcut"
},
]
import shortcut from '@system.shortcut'
shortcut.install({
success: function() {
console.log('handling success') // 创建成功
},
fail: function(data, code) {
// 创建失败,请在设置中开启创建桌面应用权限
console.log(`handling fail, code = ${code}, errorMsg=${data}`)
}
})
<template>
<div class="wrapper">
<text id='text' @click='setValue'>存储数据</text>
<text id='text' @click='getValue'>获取数据</text>
</div>
</template>
<script>
import storage from '@system.storage'
import prompt from '@system.prompt'
export default {
setValue(){
storage.set({
key: 'test',
value: '11111',
success: function(data) {
prompt.showToast({
message: '存储成功'
})
},
fail: function(data, code) {
console.log(`handling fail, code = ${code}`)
}
})
},
getValue(){
storage.get({
key: 'test',
success: function(data) {
prompt.showToast({
message: data
})
},
fail: function(data, code) {
console.log(`handling fail, code = ${code}`)
}
})
}
}
</script>
import { fetch } from "@system.fetch";
import { getStorage, setStorage } from './storage'
const api = 'xxx'
const hasToken = async () => {
const token = await getStorage('token')
return !!token
}
// 将与后端约定的数据统一添加在请求头中
const getHeaders = async () => {
const token = await getStorage('token')
return {
token,
....
}
}
export const httpGet = async (url, data = {}, header = {}) => {
await hasToken()
const headers = await getHeaders()
return new Promise((resolve, reject) => {
fetch({
url: api + url,
data,
method: 'GET',
responseType: 'json',
header: {
...headers,
...header
},
success(data) {
resolve(data.data)
},
fail(err) {
reject(err)
}
})
})
}
export const httpPost = async (url, data = {}, header = {}) => {
await hasToken()
const headers = await getHeaders()
return new Promise((resolve, reject) => {
fetch({
url: api + url,
data,
method: 'POST',
responseType: 'json',
header: {
...header,
...headers
},
success(data) {
if (data.data.status === 1004) {
router.replace({
uri: '/pages/Login'
})
} else {
resolve(data.data)
}
},
fail(err) {
reject(err)
}
})
})
}
export default {
httpGet,
httpPost
}
获取设备信息 如屏幕高度
首先并不是所有机型都支持在h5页面跳转到快应用页面的,因此在进行跳转之前需要先判断当前机型是否支持跳转做好兜底。
h5跳转到快应用有以下几种方式
可以通过deeplink的形式进行跳转
deeplink支持格式如下:
http://hapjs.org/app//[path][?key=value]
参数说明如下:
package: 应用包名(与manifest.json中package属性相同),必选
path: 应用内页面的 path,可选,默认为首页
key-value: 希望传给页面的参数,可选,可以有多个
快应用内获取参数: 快应用内会自动获取key-value并赋值给public
内的同名参数
若是public内没有同名参数,则不会新增这个属性(相当于️成功获取)
说明:不同的厂商对该能力可能有不同限制,使用前请和相应厂商确认(本人试了华为、荣耀、小米、OPPO的几部测试机,目前并没有发现问题)
流程
<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/qa_router.min.js"></script>
在网页嵌入如上js后,会给window对象添加一个方法channelReady
,可以通过这个方法检验当前机型是否支持跳转;if (window.channelReady) {
window.channelReady(function (bAvailable) {
// bAvailable为true表示允许跳转
// bAvailable为false表示不允许跳转
})
}
clickmethod(){
if (window.channelReady) {
window.channelReady(function (bAvailable) {
if (bAvailable) {
location.href = `https://hapjs.org/app/com.klang.benz/pages/Front?phone=${_this.phone}&channel=${_this.channel}`
}else{
// 不允许跳转- 兜底(下载对应app)
}
}
}else{
// 不允许跳转- 兜底(下载对应app)
}
}
h5点击组件是指:网页开发者可以在其H5 页面中使用快应用官方推荐的点击组件,用于跳转指定快应用。使用点击组件时,必须由用户主动点击方可发起跳转快应用请求。
<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/qa_router.min.js"></script>
在网页嵌入如上js后,会给window对象添加一个方法channelReady
,可以通过这个方法检验当前机型是否支持跳转;tips: 虽然官方文档上说会将参数赋值给public同名属性,但是在真机上
很多型号接收不到参数
!!!
官方文档不推荐使用url配置跳转方式进行跳转
<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/routerinline.min.js"></script>
嵌入之后会在window上添加appRouter
和 channelReady
方法,其中channelReady用来检验是否可以跳转,appRouter方法用来进行跳转,具体语法请看文档。在进行快应用开发时我最先使用的是“h5点击组件跳转”,然后发现参数都接收不到,因此我就尝试了“deeplink”方式进行跳转,万幸~这次可以成功拿到参数。
但是此时出现了一个新的问题:有的手机点点击跳转中间页的“手动打开”不起作用,如下
流程相当于被卡在这里了…
但是同样的跳转地址我在快应用预览版->启动应用测试->Deeplink启动测试里面进行跳转就可以成功打开,如下:
让我不禁怀疑是不是h5里面的跳转写的有问题,经过一番测试发现是浏览器的问题,只有手机自带的浏览器才有下面这个请求提示
!!!
总结: 有的机型在点击手动打开时就可跳转到快应用,而有的手机型号点击时无反应,若是在手机自带浏览器会弹出下面打开快应用中心提示,若是其他浏览器则会中断流程…
问题描述: 在快应用中使用window对象在预览时并没有报错,但是在真机调试时报错 window is not defiend
原因:window对象是相对于Web浏览器而言的,它并不是ECMAScript内置对象,它是浏览器的Web API。
而快应用并不是在浏览器中打开而是在node环境中打开,因此不能使用window以及window的属性/对象。
快应用只使用js的语法只能使用ECMSSCript,不能使用BOM、DOM。
就像之前所说的,所谓样式兼容性问题是因为我们一直将快应用组件当作原生html标签使用。
接下来就是按照我们之前编写web页面的一些习惯 针对一些不兼容样式进行说明~
@import './style.css';
在快应用中,单位仅支持px、dp、%
快应用的px单位与传统 web 页面不同,px是相对于项目配置基准宽度的单位,已经适配了移动端屏幕,其原理类似于rem。
在config.designWidth
中定义项目配置基准宽度,默认750
设计稿1px / 设计稿基准宽度 = 框架样式1px / 项目配置基准宽度
也就是说项目配置基准宽度设置为设计稿基准宽度之后, 框架样式1px = 设计稿1px (不需转换即可使用并且适配移动端屏幕)!
快应用布局框架使用 border-box 模型
,暂不支持 手动指定 box-sizing 属性(快应用中只能使用border-box 盒模型不能使用content-box盒模型)。
在快应用中组件默认采用的都是 弹性布局
的方式进行布局。
弹性布局不可以取消 ! ===> 在快应用中display只有flex与none取值情况,
display: flex ; // 弹性布局
display: none; // 消失
若是不想子元素在一行排列 可以使用修改主轴方向
flex-direction: column;
注意:在弹性布局中 ===> 若是子元素的高度/宽度总和大于父元素的高度或宽度,不会出现滚动条,而是子元素的宽/高 收缩。
若是需要使用滚动条,可以使用list组件!
在vue中 是用动态类名使用的是指令,如下
<text :class="activeTag==index ? 'activetag' : ''" for='(index, item) in tags'>{{item}}</text>
而在快应用中使用动态类名使用的是{{}}
,如下
<text class="{{activeTag==index ? 'activetag' : ''}}" for='(index, item) in tags'>{{item}}</text>
在很多情况下,我们需要通过动态切换类型来改变元素的的样式,在快应用中注意,切换类名时,类名必须在目标元素
上,不然没效果!
比如设置在父元素上
.active{
text{
color: red; // 没效果
}
}
我给text的父元素添加active类名然后修改text元素文本的颜色,但是发现没有效果;但是把类名动态添加在text标签上就发现样式可以正常切换了。
.active{
color:red;
}
行内样式不支持动态编写 ----> 可以使用computed或methods
<div style='{{background-image:url(imgurl)}}' class='www'>div>
private:{
imgurl: 'https://martin-upload.wcar.net.cn/web/2021/11/6bbf95698459f15b0050cb0d8e9e3484.png'
}
上述代码不能正常显示图片,个人猜测是因为识别不出变量imgurl,若是想样式中的数据动态切换,可以采用computed与methods
<div style="{{returnStatusImage()}}" class='www'>div>
private: {
text: '快应用是什么?',
status:0
},
returnStatusImage() {
switch (this.status) {
case 0:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/6bbf95698459f15b0050cb0d8e9e3484.png)'
break;
case 1:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/07167f84c6dbf2679a6b1744acdd6ae9.png)'
break;
case 2:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/743cbd9439d241cb6c8af9aeb85b312e.png)'
break;
case 3:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/12/5459fe6f0978ca211dc7034b903547c2.png)'
break;
case -1:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/12/5459fe6f0978ca211dc7034b903547c2.png)'
break;
case 4:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2022/02/9ff11fe02d56737ed45dec1ff626a194.jpg)'
break;
default:
return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/6bbf95698459f15b0050cb0d8e9e3484.png)'
}
},
background: linear-gradient(53deg, #F0E6D5 0%, #F0DFC3 100%);
background: red;
background-color:red;
快应用中, css不支持overflow样式,因此无法设置超出滚动或显示!
[1] 若是想在组件内滑动可以使用list组件
[2] 若是希望子节点能够超出父节点显示,不会被父节点裁剪,在1100+版本在元素上添加了overflow属性
<div overflow='visible'></div>
但是经过检验,目前在模拟器上没有问题,但是真机超过父组件的部分还是会被隐藏!
那像上图所示应该如何设置呢?
在快应用中border-radius只接受一个值作为属性值
border-radius:30px 20px 10px 0; // 四个圆角都会设置为30px
不支持30px 20px 10px 0作为单位,在编译时会将第一个值后面的值看作为单位border-radius:30px 20px 10px 0; // 四个圆角都会设置为30px
border-top-left-radius:30px; // 左上
border-top-right-radius:30px; // 右上
border-bottom-left-radius:30px; // 左下
border-bottom-right-radius:30px; // 右下
快应用中不支持盒子阴影。
在web页面的css中,定位的层级是通过z-index来控制的,z-index属性的属性值数值越大,则层级越高。
在快应用的css中,定位的层级是根据组件在template中的顺序决定的,后来者居上
,写在后面的组件会将写在前面的组件覆盖掉。
渲染之后样式没问题,点击左侧按钮发现没有返回并且没有走返回方法!
原因:因为在快应用中的层级讲究后来者居上和定位没有关系,text标签在image标签后面,因此text标签覆盖了image导致image标签的事件不起作用!
解决: 只需要将text标签与image标签换一个顺序即可!
<div class='titlebar'>
<text>设置</text>
<image src="https://img.iwave.net.cn/other/5f3f779274fbe300917c54ba94dc9797.png" @click='back'></image>
</div>