快应用与h5交互
h5跳转到快应用
[1] 判断当前环境是否支持组件跳转快应用
首先并不是所有机型都支持在h5页面跳转到快应用页面的,因此在进行跳转之前需要先判断当前机型是否支持跳转做好兜底。
- 首先在网页嵌入如下 js
在网页嵌入如上js后,会给window对象添加一个方法<script type="text/javascript" src="//statres.quickapp.cn/quickapp/js/qa_router.min.js"></script>
channelReady
,可以通过这个方法检验当前机型是否支持跳转;if (window.channelReady) { window.channelReady(function (bAvailable) { // bAvailable为true表示允许跳转-跳转 // bAvailable为false表示不允许跳转-兜底 }) }else{ // 不允许跳转-兜底 }
- 注意:并不是所有机型都支持如上判断
[2] h5跳转到快应用
h5跳转到快应用有以下几种方式
(1)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
内的同名参数若是public内没有同名参数,则不会新增这个属性(相当于🈚️成功获取)
说明:不同的厂商对该能力可能有不同限制,使用前请和相应厂商确认(本人试了华为、荣耀、小米、OPPO的几部测试机,目前并没有发现问题)
流程
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)
}
}
(2)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同名属性,但是在真机上
很多型号接收不到参数
!!!
(3)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里面的跳转写的有问题,经过一番测试发现是浏览器的问题,只有手机自带的浏览器才有下面这个请求提示
!!!
总结: 有的机型在点击手动打开时就可跳转到快应用,而有的手机型号点击时无反应,若是在手机自带浏览器会弹出下面打开快应用中心提示,若是其他浏览器则会中断流程…
web组件
作用:用于显示在线的 html 页面(可以嵌入三方页面或者某些不太重要的页面)
h5页面嵌入快应用
可以使用web组件
将h5页面嵌入快应用页面中
缺点:打开会比原生慢一点,可能存在白屏现象。
示例:
<web src='https://doc.quickapp.cn/tutorial/framework/lifecycle.html'></web>
渲染结果如下:
在当前h5页面嵌入快应用之后,快应用就可以和当前h5页面进行消息互通了。
快应用发送消息到h5页面
-
语法
this.$element('web').postMessage({ message: messageString, success: function(){}, fail: function(){} })
-
注意点1:message必须为
String
类型,若是传递其他数据类型如对象,在真机环境会报错this.$element('web').postMessage({ message: {str: '11111'} // 发送消息为一个对象 })
上述代码报如下错误
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)
this.$element('web').postMessage({ message: '111111' //发送的消息为111111 })
上述代码成功发送
若是想发送对象类型可以使用
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) } } }
-
注意点2:注意发送数据的时机,发送数据一定要等待
网页
渲染完毕之后,否则在网页端将接收不到数据示例:
我想在页面渲染完成之后发送信息给web页面,因此我选择在快应用的onReady生命周期发送数据
onReady(){ this.$element('web').postMessage({ message: '111111' }) }
但是我发现在网页在拿不到指定的信息
原因是因为在发送数据的时候web网页还没有渲染完成!
我们可以在web组件的
pagefinish
事件时传送数据,此事件在web页面渲染完成时触发
!@pagefinish="pagefinish"
pagefinish(){ this.$element('web').postMessage({ message: '111111' }) }
h5页面接收快应用发送的消息
当网页被嵌入快应用时,默认会向该页面的windows中添加system
对象,该对象上存在onmessage
方法用于接收快应用中发送过来的消息。
注意: 该方法只有在快应用嵌套的web页面中可以使用,否则这个方法将不存在(在web页面做好兼容)!
mounted () {
if (window.system && window.system.onmessage) {
window.system.onmessage = function (data) {
console.log('message received: ' + data) // data为快应用发送的消息
}
}
}
h5页面发送消息到快应用
当网页被嵌入快应用时,默认会向该页面的windows中添加system
对象,该对象上存在postMessage
方法用于向快应用中发送消息。
注意: 该方法只有在快应用嵌套的web页面中可以使用,否则这个方法将不存在(在web页面做好兼容)!
// 通过条件判断当前页面是否嵌入在快应用中(做好兼容)
if (xxx) {
window.system.postMessage(string)
window.system.postMessage(JSON.stringify(obj))
}
tips: postMessage方法的参数为string,若是想传输对象需要使用stringify进行转换
快应用页面接收h5页面传递的消息
@message="message"
message(data){
// data:{message: messageString, url: urlString}
}
通信前提- trustedurl
web页面可以与快应用通信的前提是:只有在互相信任的页面路径才会允许通信。
web组件的trustedurl
属性就是表示可信任的网址的集合。只有 trustedurl 中链接或者 src 链接的网页可以和框架进行双向通信(支持正则表达式)。
有人可能会疑惑:我没有添加trustedurl属性,但是现在通信没有问题? 原因是因为在默认情况下会添加web组件的src属性到trustedurl中。
因此若是URL永远不变,则可以省略,若是路径携带参数或url不是固定值,则必须添加trustedurl!