目录
- 官网
- 概述
- 开发前提
- [1] 安装IDE
- 问题-IDE打开是英文
- [2] 创建项目
- [3] 运行项目
- [4] 项目结构
- 开发调试
- USB真机调试
- 扫码调试
- 上传发布
- 步骤
- error: 版本号必须高于上一个版本的
- 页面(文件)
- 组件
- 快应用组件
- 常用总结
- 快应用组件
- 第三方组件库
- 页面级组件
- 自定义组件(子组件)
- 引入自定义组件(子组件)
- 父组件给子组件传值
- 子组件给父组件进行传值
- js
- 快应用全局对象global
- this--vm实例化对象
- 事件
- 数据定义
- 计算属性
- 页面切换
- 声明式导航
- 路由跳转
- 路由传参
- 接收参数
- 回传参数
- app.ux
- APP的生命周期
- 公共方法- $app && $app. $def
- 封装-缓存数据
- 全局数据- $app. $data
- 退出快应用-$app.exit
- manifest配置文件
- 应用包名-package
- 应用名称-name
- 应用图标-icon
- 应用版本名称、应用版本号- versionName、versionCode
- 路由配置-router
- 页面的生命周期
- 页面栈
- 生命周期
- 组件的生命周期
- 通用方法
- $element
- 获取某元素的宽高
- 系统接口
- [1] 检查某app是否在手机上安装
- [2] 下载应用
- [3] 检查当前是否有桌面应用
- [4] 添加桌面应用
- [5]数据存储
- [6]弹框
- [7] 接口
- [8]获取设备信息
- h5跳转到快应用
- deeplink
- h5点击组件
- url配置跳转
- 总结
- 逻辑问题
- window is not defined
- 样式问题
- 引入css样式文件
- [1]选择器
- [2]盒模型
- [3]样式布局-弹性布局
- [4-1]样式切换 - 类名的动态切换
- [4-2] 样式切换 - 行内样式动态切换
- [5]background
- [6]overflow
- [7]border-radius
- [8]盒子阴影
- [9] 单位
- [10] 定位
官网
快应用官网
概述
从上述可以看出 快应用的覆盖面比较窄,仅支持10种手机型号,像iPhone、三星等都是不支持快应用的~。但是快应用的优势还是比较明确的无需安装、即点即用,用完即走,简单来说就是比较方便,可以提升用户体验度。用户可以在 URL 链接、全局搜索、应用商店、浏览器、负一屏、系统桌面、PUSH、语音助手、安全中心、垃圾清理、信息助手、天气、短信模板、日历、个性主题、文件管理等等任何地方作为入口打开快应用…
开发前提
[1] 安装IDE
开发快应用的前提就是安装快应用开发工具
问题-IDE打开是英文
第一次打开时显示为英文是因为配置还没有加载好,关闭之后重新打开显示的就是中文了。
[2] 创建项目
点击如上新建项目打开新建工程界面
新建工程界面展示如上,可以选择快应用、快应用卡片、 快应用(Webview) 三类项目
选择某一模版,点击下一步,项目创建完成。
[3] 运行项目
如果您基于官方模版,创建新项目,需要先安装依赖,才能正常运行。您可以使用 yarn 或 npm i 命令,在终端运行来安装依赖,然后运行项目。
也可点击下图的 安装依赖,重新启动编译来启动项目(其实就是快捷键)。
[4] 项目结构
开发调试
在开发过程中,快应用运行效果,会在主界面右侧的模拟器中显示。
但是模拟器中运行的效果和真机存在差异
- UI: 很多UI在模拟器上显示正确但是在真机上显示错乱
- API: 模拟器尚未支持全部 API
因此实际开发过程中还需要使用真机来预览,来调试快应用的实际运行情况。
USB真机调试
-
前提:准备一台安卓手机,确保手机处于开发者模式
若是不确定手机是否处于开发者模式: 设置 -> 关于手机 -> 软件版本 -> 多次点击软件版本号至提示“您已处于开发者模式,无需进行此项操纵”为止
-
步骤
[1] 使用数据线连接电脑与手机
确保数据线可以传输数据而不是只能用于充电;否则会报错–> 找不到Android
[2] 点击 IDE 工具栏的「USB 调试」开始调试
每次运行调试时,开发者工具会检测您的手机是否安装了【快应用预览版】【快应用调试器】。如果未安装,开发者工具将自动安装。 若是已安装会自动打开快应用预览版进入快应用首页进行调试,与此同时电脑端会打开调试页面。
扫码调试
- [1]在快应用调试器下载地址: 官网->开发支持->开发工具->帮助中心->资源下载下载快应用调试器 与 快应用预览版;
- [2] 点击如下二维码icon打开二维码并使用快应用调试器扫描二维码可正常在手机上进行调试
上传发布
步骤
-
打包: 点击顶部工具栏的打包按钮
若无签名,会索引您添加签名
点击完成之后会自动在项目根目录生成一个sign
文件里面存储签名。
若是存在签名:快应用开发工具将自动生成 release 签名的包,既可以直接使用rpk包上传至官网也可上传包管理平台,如下:
-
包管理平台: 在打包完成之后可以点击上传包管理平台上传本次rpk文件,上传成功之后会出现一个二维码和包管理平台的链接,您可使用调试器的扫码功能,打开此快应用
-
上传至官网:在开发完成之后,若您想发布上线该快应用,可以通过快应用开发工具的「上传」功能,将其上传至官网的开发者中心,后续可在官网按照流程填写相关信息后,发布上线快应用(当然,您也可以在后台,手动提交 RPK 包)
error: 版本号必须高于上一个版本的
问题: 在更新版本上传rpk文件时,提示版本号必须高于上一个版本
。
原因:出现这个问题的原因是快应用官方以配置 manifest.json 的属性versionCode
的值来确认版本更新,官方要求每次上架更新需要将该值手动 自增1。很多同学会误以为修改 versionName 来更新版本,versionName 应该是属于那种显示在应用商店的版本号!
我就是在版本迭代时只是修改了versionName属性值但是没有修改versionCode属性的值,因此在发布时一直提示“版本号必须高于上一个版本”。
页面(文件)
现在回想一下Vue页面构成
<template>
<!-- template里只能有一个根节点 -->
<!-- 可以是原生html,或是基于html封装的一些组件-->
</tempalte>
<script>
export default{
// 配置项
}
</script>
<style lang='less/scss'>
css/less/scss
</style>
ux文件与vue文件结构完全相同,但是语法有所区别
- [1] 快应用
不支持原生HTML
,开发快应用只能使用快应用组件和基于快应用组件封装的组件; - [2] 快应用的样式使用的也是css,但是
存在很多样式兼容问题
,需要后面一一记录兼容性问题产生的原因是:每个快应用组件支持的样式不一样,我们如果一直按照使用原生HTML的思维去使用快应用组件,就会感觉某些样式不起作用了,就会感觉存在某些兼容性问题!
- [3] 快应用的逻辑使用也是ECMAScript,不包含BOM与DOM
组件
快应用组件
在快应用中不支持使用原生html —> 若是使用原生html直接不显示!
因此在开发快应用时只能使用快应用组件~比如div、text…
此时需要注意的是:这些组件不是原生html标签,在使用时需要关注组件支持的样式、事件以及是否能存放文本
!
举例说明
-
接受子组件
-
接受的样式
-
是否支持存放文本
-
检查
因此当渲染结果和自己想象的不同时可以直接查看官网文档说明。
也可在控制台输出里面查看提示
常用总结
- [1] 文本必须包裹在span/a/text组件中,否则不显示
- [2] span必须作为text/a/span组件的子组件,否则不显示;
快应用组件
常用的快应用组件
第三方组件库
- https://vivoquickapp.github.io/apex-ui-docs/
- https://jdsecretfe.github.io/quist-ui/
- https://quickappcn.github.io/qaui/
页面级组件
在pages
中定义的组件被称为页面级组件。
页面级组件(等同于Vue页面),通过路由配置可以进行页面跳转。
自定义组件(子组件)
在components
中定义的组件被称为自定义组件。
自定义组件(等同于Vue的子组件),将使用比较多的部分进行封装,可以多次使用。
引入自定义组件(子组件)
举例说明
父组件给子组件传值
- 父组件给子组件传值使用的是props,其语法与vue 的props传值类似,可以规定传值类型、默认值等,还可以进行数据校验
-
在父组件给子组件进行传值时使用的是短横线分割命名,在子组件中通过props 接收时使用的是驼峰命名
-
子组件接收属性时,可以设置默认值。当调用子组件没有传入该数据时,将会自动设为默认值。
-
父子间的数据传输是单向性的,父组件 prop 数据更新,子组件的数据会刷新为最新值;子组件的 prop 值发生改变,并不会改变父组件中值。但是prop 类型事数组或者对象,自组件变化会影响到父组件的值,这意味着你不应该在一个子组件内部改变 prop 的值,这是危险性操作。
-
在进行校验时,验证顺序是 必填项检查 -> 类型检查 -> 函数检查
-
语法
props: { prop1: [String、Number、Boolean、Function、Object、Array], // 仅类型检查 prop2Object: { type: [String、Number、Boolean、Function、Object、Array], // 类型检查 required: true, // 必填项检查 validator: function(value) { return true // 符合检查 return false // 不符合检查 } }
-
举例说明: 在父组件接收三个参数分别为name( 字符串类型且必传),年龄(数字类型,只能接受18,19,29三个中的某一个数字),地址(字符串类型,不能超过18个字, 默认为中国)并将展示在页面上
父组件
<import name='son' src='../../components/son.ux'></import> <template> <div> <son p-name="{{name}}" p-age="{{age}}"></son> </div> </template> <script> export default{ private: { name:'chaochao', age:'20' } } </script>
子组件
<template> <div> <text>{{pName}}</text> <text>{{pAge}}</text> <text>{{pArea}}</text> </div> </template> <script> export default{ data(){ return{ name:'子组件' } }, props: { pName: { type: String, required: true }, pAge: { type: Number, required: true, validator: function(value) { return [18, 19, 20].includes(value) } }, pArea: { type:String, default:'中国', validator: function(value) { return value.length<18 } } }, } </script>
此时页面能正常显示内容 chaochao20中国,但是控制台会报出警告如下:
-
子组件给父组件进行传值
语法
// 子组件
this.$dispatch('子组件触发事件名',值)
// 父组件
onInit(){
this.$on('子组件触发事件名',触发的父方法方法)
}
// 子组件
this.$emit(方法名,值)
// 父组件
<son on方法名=‘父组件方法’></son>
举例说明:在子组件修改父组件传过来的name属性
-
方式1
- 子组件:触发父组件自定义事件
editname(){ this.$dispatch('dispatchEvt',{ name:'niuniu' }) }
- 子组件:监听自定义事件触发
打印结果如下:onInit(){ this.$on('dispatchEvt',this.editName) }, editName(value){ console.log(value) }
因此我们可以通过如下方式进行赋值editName(value){ this.name = value.detail.name }
- 子组件:触发父组件自定义事件
-
方式2
- 子组件
editname(){ this.$emit('editName',{ name:'niuniu' }) }
- 父组件
<son p-name="{{name}}" p-age="{{age}}" onedit-name='editname'></son>
打印结果如下:editname(value){ console.log(value) }
因此我们可以通过如下方式进行赋值editName(value){ this.name = value.detail.name }
- 子组件
tips: 当传递结束后,可以调用value.
stop()
来结束传递,否则会一直传递下去
js
快应用全局对象global
在快应用中不能使用BOM、DOM,因此也不能使用window作为全局对象。
在快应用中可以使用global
访问全局对象
在快应用中global对象可以直接使用,我们可以将封装的公共方法添加在global对象上(类似于将封装的公共方法添加在vue实例化对象上)。
this–vm实例化对象
this指向的是vm实例化对象(使用与vue2.x中相同)。
事件
在快应用上进行事件绑定与vue2.x中相同(唯一的区别是在vue2.x中是将方法定义在methods配置项中,定义在methods配置项中的方法会被平铺在实例化对象上;而快应用中是直接将定义的方法平铺在实例化对象上–不定义在methods配置项中)
数据定义
定义数据时:页面级组件定义数据时可以根据需要将数据定义在data、public、protected、private属性中(data不可与public、protected、private同时存在),而自定义组件中数据模型只能使用data 属性
计算属性
计算属性
页面切换
官网
声明式导航
在快应用中可以通过 a组件
(类似vue中的link组件)进行声明式导航,不仅可以跳转到站内页面、还可以通过webView加载网页、掉起电话、短信、邮件…
<template>
<div class="wrapper">
<a href="/pages/Home">去首页1</a>
<a href="pages/Home">去首页2</a>
<a href="tel:10086">打电话</a>
<a href="sms:10086">发短信</a>
<a href="mailto:example@xx.com">发邮件</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:example@xx.com'
break;
case 6:
uri = 'https://www.baidu.com/'
break;
}
router.push({
uri
})
}
}
</script>
路由传参
使用a组件或router接口进行路由跳转时----传递参数与接口参数方式一致,在此以router.push方法进行说明。
- 若是通过a组件进行路由跳转时可以通过在uri上拼接**?key=value**的形式进行路由传参
<a src='xxx?key1=value1&key2=value2'>路由跳转</a>
- 若是通过router接口进行路由跳转则有两种方式
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 中增加缓存的数据,并提供读写缓存数据的能力来实现。
封装缓存数据方法
app.ux
APP的生命周期
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}`
})
}
上述代码
- 进入系统时走: onCreate、onRequest、onShow;
- 通过router.push进行页面跳转时不走任何回调
- 切换后台时走: onHide
- 切回项目时走:onShow
- 存在错误时走: onError
公共方法- $app && $app. $def
[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()
全局数据- $app. $data
在实际开发过程中,若是存在一些常量切在项目的多个地方使用时,可以将该数据存储在manifest.json
配置项的config.data
中。
在使用时可以通过$app.$data
去获取。
退出快应用-$app.exit
this.$app.exit() // 退出开应用,结束应用生命周期
manifest配置文件
manifest配置文件1-配置信息
manifest配置文件2
应用包名-package
应用包名,是区别于其他应用的唯一标识。
推荐采用 com.company.module 的格式,示例如下:
{
"package": "com.example.demo"
}
应用名称-name
应用名称,6 个汉字以内,与应用商店保存的名称一致;框架提供保存到桌面的功能,桌面上显示的应用名即为此属性;示例如下:
{
"name": "发票小助手"
}
应用图标-icon
规则为正方形(不能是圆角),且务必无白边;
{
"icon": "/assets/images/logo.png"
}
在上传时显示的图标img即为此处的图标。
应用版本名称、应用版本号- versionName、versionCode
应用版本名称、版本号为开发者的应用包维护的版本信息;
应用版本名称为主版本.次版本格式;
应用版本号为整数,从 1 开始,每次更新上架请自增 1;
示例如下:
{
"versionName": "1.0",
"versionCode": 1
}
在上传时版本以versionCode为准,在应用商店展示的版本号以versionName为准
路由配置-router
router,路由,用于定义页面的实际地址、跳转地址。如果 ux 页面没有配置路由,则不参与项目编译。一个目录下最多只能存在一个主页面文件(不包括组件文件)。
- entry:表示首页名称,若是没有配置entry属性默认pages第一个为首页路径。
"router":{ "entry": "首页页面目录名" }
- pages: 页面配置列表
"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" } }
页面的生命周期
页面栈
web页面开发:在浏览器页签中每次只能有一个页面,当前页签打开另一个页面,上个页面就销毁了;
在浏览器页签打开某个页面1(页面1初始化、渲染…),在当前页签打开页面B(页面1销毁,页面2初始化、渲染…)
快应用开发:可以同时运行多个页面,但是每次只显示其中一个页面。
页面栈中就是存储当前打开的页面!
生命周期
组件的生命周期
生命周期
- onInit:数据已经准备好,可以开始使用页面中的数据
- onReady: 模板已经编译完成,可以获取dom节点
- onShow: 页面重新显示时调用
- onHide: 页面被隐藏时调用
- onDestory: 页面被销毁时调用
- onBackPress
- onMenuPress
- onRefresh
- onConfigurationChanged
- onReachTop
- onReachBottom
- onPageScroll
通用方法
通用方法,即提供给所有组件调用的方法。
$element
获取指定 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
[1] 检查某app是否在手机上安装
- 官方文档:官方文档
- 接口:
system.package
的hasInstalled方法 - 作用:检查某app是否在已经在手机上安装
- 使用
- [1] 接口声明- 在配置文件manifest.json中声明
"features": [ { "name": "system.package" }, ]
- [2] 在需要的地方导入并使用
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}`) } })
- [1] 接口声明- 在配置文件manifest.json中声明
[2] 下载应用
- 官方文档:官方文档
- 接口:
system.package
的install方法 - 作用:下载某app
- 使用
- [1] 接口声明- 在配置文件manifest.json中声明
"features": [ { "name": "system.package" }, ]
- [2] 在需要的地方导入并使用
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}`) } })
- [1] 接口声明- 在配置文件manifest.json中声明
[3] 检查当前是否有桌面应用
- 官方文档:官方文档
- 接口:
system.shortcut
的hasInstalled方法 - 作用:检查某app当前是否有桌面应用
- 使用
- [1] 接口声明- 在配置文件manifest.json中声明
"features": [ { "name": "system.shortcut" }, ]
- [2] 在需要的地方导入并使用
import shortcut from '@system.shortcut'
shortcut.hasInstalled({ success: function(res) { // res 为true表示已创建图标 // res weifalse表示未创建图标 } })
- [1] 接口声明- 在配置文件manifest.json中声明
[4] 添加桌面应用
- 官方文档:官方文档
- 接口:
system.shortcut
的install方法 - 作用:为某app添加桌面应用
- 使用
- [1] 接口声明- 在配置文件manifest.json中声明
"features": [ { "name": "system.shortcut" }, ]
- [2] 在需要的地方导入并使用
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}`) } })
- [1] 接口声明- 在配置文件manifest.json中声明
[5]数据存储
- 官方文档:官方文档
<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>
[6]弹框
- 官方文档:官方文档
- 弹出框一共有三种
- toast提示框-showToast
- dialog对话框-showDialog
- 列表框-showContextMenu
[7] 接口
- 官方文档:官方文档
- 请求封装
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 }
[8]获取设备信息
获取设备信息 如屏幕高度
h5跳转到快应用
首先并不是所有机型都支持在h5页面跳转到快应用页面的,因此在进行跳转之前需要先判断当前机型是否支持跳转做好兜底。
h5跳转到快应用有以下几种方式
deeplink
可以通过deeplink的形式进行跳转
-
deeplink支持格式如下:
http://hapjs.org/app/<package>/[path][?key=value]
- https://hapjs.org/app//[path][?key=value]
- hap://app//[path][?key=value]
-
参数如下:
- package: 应用包名(与manifest.json中package属性相同),必选
- path: 应用内页面的 path,可选,默认为首页
- key-value: 希望传给页面的参数,可选,可以有多个
-
快应用内参数获取: 快应用内会自动获取key-value并赋值给
public
内的同名参数- 注1:若是public内不同名参数,则不会新增这个属性 -> 相当于没有获取这个参数
- 注2: 不同的厂商对该能力可能有不同限制,使用前请和相应厂商确认(本人试了华为、荣耀、小米、OPPO的几部测试机,目前并没有发现问题)
-
举例说明
<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/qa_router.min.js"></script>
在网页嵌入如上js后,会给window对象添加一个方法
channelReady
,可以通过这个方法检验当前机型是否支持跳转;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点击组件是指:网页开发者可以在其H5 页面中使用快应用官方推荐的点击组件,用于跳转指定快应用。使用点击组件时,必须由用户主动点击方可发起跳转快应用请求。
- 在网页嵌入如下 js:
在网页嵌入如上js后,会给window对象添加一个方法<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/qa_router.min.js"></script>
channelReady
,可以通过这个方法检验当前机型是否支持跳转;
在网页嵌入如上js后,会有一个全局组件 ,可以在页面合适位置插入(样式可自行调整),组件属性如下
tips: 虽然官方文档上说会将参数赋值给public同名属性,但是在真机上
很多型号接收不到参数
!!!
url配置跳转
官方文档不推荐使用url配置跳转方式进行跳转
- 在网页嵌入如下js文件
嵌入之后会在window上添加<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/routerinline.min.js"></script>
appRouter
和channelReady
方法,其中channelReady用来检验是否可以跳转,appRouter方法用来进行跳转,具体语法请看文档。
总结
在进行快应用开发时我最先使用的是“h5点击组件跳转”,然后发现参数都接收不到,因此我就尝试了“deeplink”方式进行跳转,万幸~这次可以成功拿到参数。
但是此时出现了一个新的问题:有的手机点点击跳转中间页的“手动打开”不起作用,如下
流程相当于被卡在这里了…
但是同样的跳转地址我在快应用预览版->启动应用测试->Deeplink启动测试里面进行跳转就可以成功打开,如下:
让我不禁怀疑是不是h5里面的跳转写的有问题,经过一番测试发现是浏览器的问题,只有手机自带的浏览器才有下面这个请求提示
!!!
总结: 有的机型在点击手动打开时就可跳转到快应用,而有的手机型号点击时无反应,若是在手机自带浏览器会弹出下面打开快应用中心提示,若是其他浏览器则会中断流程…
逻辑问题
window is not defined
-
问题描述: 在快应用中使用window对象在预览时并没有报错,但是在真机调试时报错 window is not defiend
-
原因:window对象是相对于Web浏览器而言的,它并不是ECMAScript内置对象,它是浏览器的Web API。
而快应用并不是在浏览器中打开而是在node环境中打开,因此不能使用window以及window的属性/对象。
快应用只使用js的语法只能使用ECMSSCript,不能使用BOM、DOM。
样式问题
就像之前所说的,所谓样式兼容性问题是因为我们一直将快应用组件当作原生html标签使用。
接下来就是按照我们之前编写web页面的一些习惯 针对一些不兼容样式进行说明~
引入css样式文件
@import './style.css';
[1]选择器
- 支持标签选择器、类选择器、id选择器,暂不支持其它选择器;
- 继承:不支持样式继承;
[2]盒模型
快应用布局框架使用 border-box 模型
,暂不支持 手动指定 box-sizing 属性(快应用中只能使用border-box 盒模型不能使用content-box盒模型)。
[3]样式布局-弹性布局
在快应用中组件默认采用的都是 弹性布局
的方式进行布局。
-
弹性布局不可以取消 ! ===> 在快应用中display只有flex与none取值情况,
display: flex ; // 弹性布局 display: none; // 消失
-
若是不想子元素在一行排列 可以使用修改主轴方向
flex-direction: column;
-
注意:在弹性布局中 ===> 若是子元素的高度/宽度总和大于父元素的高度或宽度,不会出现滚动条,而是子元素的宽/高 收缩。
若是需要使用滚动条,可以使用list组件!
[4-1]样式切换 - 类名的动态切换
在很多情况下,我们需要通过动态切换类型来改变元素的的样式,在快应用中注意,切换类名时,类名必须在目标元素
上,不然没效果!
比如设置在父元素上
.active{
text{
color: red; // 没效果
}
}
我给text的父元素添加active类名然后修改text元素文本的颜色,但是发现没有效果;但是把类名动态添加在text标签上就发现样式可以正常切换了。
.active{
color:red;
}
[4-2] 样式切换 - 行内样式动态切换
行内样式不支持动态编写 ----> 可以使用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)'
}
},
[5]background
- 在快应用中background属性的作用是用来设置渐变色的,不能作为背景的复合属性。
- 起作用
background: linear-gradient(53deg, #F0E6D5 0%, #F0DFC3 100%);
- 无作用
background: red;
- 若是想设置颜色使用background-color
background-color:red;
- 起作用
- span组件添加背景色不起作用!若是想要设置背景色不要使用span组件(span不支持背景样式设置)
[6]overflow
在快应用中overflow可接受的属性值如下
overflow: visible; // 显示
overflow: hidden; // 隐藏
因此没有办法设置元素显示滚动条等
[7]border-radius
在快应用中border-radius只接受一个值作为属性值
- 若是设置2/3/4个值,则会报出警告
不支持30px 20px 10px 0作为单位,在编译时会将第一个值后面的值看作为单位border-radius:30px 20px 10px 0; // 四个圆角都会设置为30px
- 设置4个一样的值
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; // 右下
[8]盒子阴影
快应用中不支持盒子阴影。
[9] 单位
快应用中支持 px % dp单位;但是%单位在真机中显示不对!
[10] 定位
定位没有层级 ----> 存在被覆盖导致点击事件不起作用的现象