快应用官网
在开发开应用时,需要真机调试。
很多UI在模拟器上显示正确但是在真机上显示错乱 – 因此在调试时需要以真机为主。
方法1: 远程预览
直接微信扫(远程预览)二维码进入调试模式
方法2: 使用调试器调试
方法2的优势是在运行的时候若是逻辑错误可以看到运行报错,有助于我们解决问题。
比如说我在逻辑代码中使用了window对象进行事件监听,在远程预览时功能不能正常运行,但是定位不到问题的原因,使用调试器进行调试可以看到错误,能快速定位问题---- 没有window对象。
tab组件中的tab-content中的数据不支持动态增加或减少!如果要减少页面,需要先销毁掉,重新用新的实例展示数据 ===> 快应用提供了if命令,if为false时,页面不显示,并且dom节点也会移除。
<tab if='bol'>
<tab-bar>tab-bar>
<tab-content>tab-content>
tab>
但是这样将会导致每次切换tab数据加载时 tab-bar的滚动条都会滚动到初始位置(最左边),而且数据加载中tab-bar数据也会暂时消失 ===> 用户体验感不好;
我们可以只使用tab-bar来显示滚动条的tab数据,底部content内容使用普通组件div进行显示!
list-item — type属性必填 不然list不会滚动
若是某些不是很重要的页面,可以将web页面嵌套进快应用中 ===> 打开会比原生慢一点~
<web src='http://baidu.com'>web>
若是路由跳转的uri的schema是 http/https时,改uri默认会使用内置的web组件打开
快应用是允许快应用页面与文本页面通信的。
当网页被嵌入快应用时,默认会向该网页的windows中添加两个方法
注意: 该方法只有在嵌套的web页面且在快应用ide中浏览时可以使用,否则这两个方法将不存在!
trustedurl
,只有互相信任的页面路径才会允许通信,在默认情况下会添加web组件的src属性到trustedurl中;若是URL永远不变,则可以省略,若是路径携带参数或url不是固定值,则必须添加trustedurl;this.$element('web').postMessage({
message: messageString,
success: function(){},
fail: function(){}
})
注意点:
String
类型,若是传递其他数据类型如对象,在真机环境会报错java.lang.ClassCastException: org.json.JSONObject cannot be cast to java.lang.String
at org.hapjs.widgets.Web.f(SourceFile:535)
at org.hapjs.widgets.Web.invokeMethod(SourceFile:681)
at org.hapjs.render.b.a.a(SourceFile:30)
at org.hapjs.render.RootView.applyAction(SourceFile:1134)
at org.hapjs.render.RootView.applyActions(SourceFile:1120)
at org.hapjs.render.RootView.a(SourceFile:1105)
at org.hapjs.render.RootView.e(SourceFile:1088)
at org.hapjs.render.RootView$a.handleMessage(SourceFile:365)
at android.os.Handler.dispatchMessage(Handler.java:117)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:293)
at android.app.ActivityThread.main(ActivityThread.java:9596)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1204)
若是想发送对象类型可以使用 JSON.stringify
进行转换,但是在接收时要注意使用try catch
包裹,因为快应用默认发送的数据是对象类型且并没有stringifymounted () {
const _this = this
if (window.system && window.system.onmessage) {
window.system.onmessage = function (data) {
let d
try {
d = JSON.parse(data)
} catch (err) {
}
if (d && d.page === 'quick_app') {
_this.getInfo(d)
}
}
}
网页
渲染完毕之后,否则在网页端将接收不到数据
onReady(){
// 此处可以拿到元素的
this.$element('web').postMessage({
message: '111111'
})
}
但是我发现在网页在如下代码拿不到指定的信息mounted () {
const _this = this
if (window.system && window.system.onmessage) {
window.system.onmessage = function (data) {
console.log('data', data)
}
}
}
原因是因为在发送数据的时候web网页还没有渲染完成!web页面渲染完成时触发
!@pagefinish="pagefinish"
pagefinish(){
this.$element('web').postMessage({
message: '111111'
})
}
快应用中对于很多css样式都不兼容, 我们按照平常的习惯进行样式布局,在真机调试的时候发现样式是错乱的!
下面针对一些不兼容样式进行说明~
快应用布局框架使用 border-box 模型
,暂不支持 content-box 模型与手动指定 box-sizing 属性。
在快应用中很多组件默认采用的都是 弹性布局
的方式进行布局,div
组件是比较常用的弹性布局方式布局的元素。
display: flex ; // 弹性布局
display: none; // 消失
flex-direction: column;
在很多情况下,我们需要通过动态切换类型来改变元素的的样式,在快应用中注意,切换类名时,类名必须在目标元素
上,不然没效果!
比如设置在父元素上
.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;
在快应用中overflow可接受的属性值如下
overflow: visible; // 显示
overflow: hidden; // 隐藏
因此没有办法设置元素显示滚动条等
在快应用中border-radius只接受一个值作为属性值
border-radius:30px 20px 10px 0; // 四个圆角都会设置为30px
不支持px 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; // 右下
快应用中不支持盒子阴影。
快应用中支持 px % dp单位;但是%单位在真机中显示不对!
定位没有层级 ----> 存在被覆盖导致点击事件不起作用的现象
在项目中使用到的接口都需要在配置文件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}`)
}
})
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
}
获取设备信息 如屏幕高度
计算属性
在快应用中global对象可以直接使用,我们可以将封装的公共方法添加在global对象上(类似于将封装的公共方法添加在vue实例化对象上)
this.$app.exit() // 退出开应用,结束应用生命周期
this. $element('id名')
element.getBoundingClientRect({
success: data =>{
// data中包含元素的宽高 ,left\right\bottom\top
}
})
manifest配置文件
与传统 web 页面不同,px是相对于项目配置基准宽度的单位,已经适配了移动端屏幕,其原理类似于rem。
设计稿1px / 设计稿基准宽度 = 框架样式1px / 项目配置基准宽度
属性名不能以$
或_
开头,在页面中可通过 this
进行访问;如果全局数据属性与页面的数据属性重名,则页面初始化时,全局数据会覆盖页面中对应的属性值。
文件的目录结构如下:
src
— pages
— Demo
— index.ux
— DemoDetail
— index.ux
— Test
— test.ux
— test2.ux
entry的属性值必须为pages中的一个。
pages:{
"页面名称":{
"conponent": ' 文件夹名',
"path": "路径名"
}
}
注意事项1: 页面配置列表(key值为指定页面名称(页面对应的文件夹目录)
,value为页面详细配置; key值唯一
)
若是同一文件夹下存在多个文件,此时不能为该文件下的多个文件进行路由匹配
"pages/Test": {
"component": "test",
"path": "/test1"
},
"pages/Test": {
"component": "test2",
"path": "/test2"
}
我想为同一文件夹下的文件匹配多个路由,此时会报错 Duplicate object key(重复配置)
因此不要为同一文件夹的文件配置路由
通过路由的路径可以看出,(在没有添加path属性的情况下)路径只到指定的文件夹而不包含文件名
,因此即使是component属性值不同路由的路径也是相同的!
"pages/Test": {
"component": "test"
}
这个配置之后的路径是’pages/Test’
"pages/Test": {
"component": "test2"
}
这个配置之后的路径也是’pages/Test’
注意事项2: 若是在定义单个路由信息时,存在path属性,属性值前面一定要加/
表示当前在src文件夹下。
在定义单个路由信息时,若是没有添加对应的path属性时,页面名称就是对应的路径名
"pages": {
"pages/DemoDetail": {
"component": "index"
}
当url为’/pages/DemoDetail’就会跳转到该页面了,此时location.href的值为
http://localhost:8083/preview/pages/DemoDetail/
若是添加了path属性,页面的路径将会以path的属性值为准
"pages/DemoDetail": {
"component": "index",
"path": "/detail"
}
此时当url为’detail’或’/detail’时都会跳转到该页面,此时location.href的值为
http://localhost:8083/preview/detail/
此时注意path属性值前面一定要加/
, 不然就会匹配不到对应的页面
"pages/DemoDetail": {
"component": "index",
"path": "detail"
}
此时当当url为’detail’或’/detail’时会报错 404
http://localhost:8083/preview/detail is not found