1.背景介绍
1.1需要在小程序嵌入vr页面,同时在vr页面添加操作按钮与小程序进行通信交互
1.2开发工具:uniapp开发小程序
1.3原型图
功能:.点击体验官带看跳转小程序的体验官带看页面
功能:点击立即咨询唤起小程序弹窗打电话
2.组件及api介绍
uniapp官网:web-view | uni-app官网 (dcloud.net.cn)
web-view
web-view
是一个 web 浏览器组件,可以用来承载网页的容器,会自动铺满整个页面(nvue 使用需要手动指定宽高)。
各小程序平台,web-view 加载的 url 需要在后台配置域名白名单,包括内部再次 iframe 内嵌的其他 url 。
属性说明
属性名
类型
说明
平台差异说明
src
String
webview 指向网页的链接
allow
String
H5
sandbox
String
该属性对呈现在iframe框架中的内容启用一些额外的限制条件。
H5
fullscreen
Boolean
是否铺满整个页面,默认值:true
。
H5 (HBuilder X 3.5.4+)
webview-styles
Object
webview 的样式
App-vue
update-title
Boolean
是否自动更新当前页面标题。默认值:true
App-vue (HBuilder X 3.3.8+)
@message
EventHandler
网页向应用postMessage
时,会在特定时机(后退、组件销毁、分享)触发并收到消息。
H5 暂不支持(可以直接使用window.postMessage)
@onPostMessage
EventHandler
网页向应用实时postMessage
App-nvue
@load
EventHandler
网页加载成功时候触发此事件。
微信小程序、支付宝小程序、抖音小程序、QQ小程序
@error
EventHandler
网页加载失败的时候触发此事件。
微信小程序、支付宝小程序、抖音小程序、QQ小程序
在小程序端,用法和iframe类似,直接在src赋值在线地址
<web-view src="https://uniapp.dcloud.io/static/web-view.html"></web-view>
注意:
- 小程序仅支持加载网络网页,不支持本地html
- 小程序端 web-view 组件一定有原生导航栏,下面一定是全屏的 web-view 组件,navigationStyle: custom 对 web-view 组件无效。
- 小程序平台,
src
指向的链接需登录小程序管理后台配置域名白名单。 - 小程序平台,个人类型与海外类型的小程序使用
web-view
组件,提交审核时注意微信等平台是否允许使用 - 小程序的web-view使用的是小程序自带的浏览器内核,不同厂商不一样,详见
- 各小程序平台,web-view 加载的 url 需要在后台配置域名白名单,包括内部再次 iframe 内嵌的其他 url 。
<web-view>
加载的网页中支持调用部分 uni 接口:
方法名
说明
平台差异说明
uni.navigateTo
uni.redirectTo
uni.reLaunch
uni.switchTab
uni.navigateBack
uni.postMessage
向应用发送消息
抖音小程序不支持、H5 暂不支持(可以直接使用window.postMessage)
uni.getEnv
获取当前环境
抖音小程序与飞书小程序不支持
uni.postMessage(OBJECT)
网页向应用发送消息,在<web-view>
的message
事件回调event.detail.data
中接收消息。
Tips
- 传递的消息信息,必须写在 data 对象中。
event.detail.data
中的数据,以数组的形式接收每次 post 的消息。(注:支付宝小程序除外,支付宝小程序中以对象形式接受)
#uni.getEnv(CALLBACK)
callback 返回的对象
属性
类型
说明
plus
Boolean
App
nvue
Boolean
App-nvue, uni.webview.1.5.4.js+ 支持
miniprogram
Boolean
微信小程序
smartprogram
Boolean
百度小程序
miniprogram
Boolean
支付宝小程序
3.实际操作
下面直接来看示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
<!-- 引入ui库vant的样式 -->
<link rel="stylesheet" href="./vant.css">
<!-- 引入自定义的全局样式 -->
<link rel="stylesheet" href="./global.css">
<!-- 引入页面样式文件 -->
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="app">
<div class="flex-1">
<!-- 嵌入iframe展示vr页面 -->
<iframe class="iframe" src="https://www.realsee.com/website/customer/dataSpace/vr/kPJJK5rx" allowfullscreen="true"
frameborder="0"></iframe>
</div>
<main>
<!-- 底部操作按钮 -->
<div class="ptb-10 flex-vcenter flex-between">
<van-button type="info" @click="handleLook">体验馆带看</van-button>
<van-button type="info" @click="handleRoom">看房型</van-button>
<van-button type="info" @click="handleAsk">立即咨询</van-button>
</div>
<!-- 看房型的弹窗 -->
<van-popup v-model="showRoomPopup" round position="bottom" :overlay="false"
:style="{ minHeight: '10%',padding: '15px 10px 10px',background: 'rgba(0,0,0,.7)' }">
<div class="co-white pb-15" style="position: relative;">
<p class="text-center">房型预览</p>
<div @click="showRoomPopup = false" class="arrow-down-wrap flex-vcenter">
<span class="fs-12 mr-5">收起</span>
<van-icon name="arrow-down" />
</div>
</div>
<van-grid class="rooms-wrap" :column-num="3">
<van-grid-item v-for="(item,index) in urlParams.rooms" :key="index">
<div class="co-white rooms-item" @click="goRoom(item.url)">
<p class="rooms-content">{{item.name}}</p>
<van-image width="100%" height="100%" fit="cover" src="https://img01.yzcdn.cn/vant/cat.jpeg" />
</div>
</van-grid-item>
</van-grid>
</van-popup>
</main>
</div>
<!-- 需要引入的文件 -->
<!-- vue -->
<script type="text/javascript" src="./vue.min.js"></script>
<!-- vant ui库 -->
<script type="text/javascript" src="./vant.min.js"></script>
<!-- 微信小程序 JS-SDK -->
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<!-- 与uniapp建立连接 -->
<script type="text/javascript" src="./uni.webview.1.5.5.js"></script>
<!-- 页面的js文件 -->
<script type="text/javascript" src="./index.js"></script>
</body>
</html>
- 因为使用的vantUi库,所以下载了vant.min.js,想用vue开发所以下载了vue.min.js,这2个不重要
- 需要引入微信小程序 JS-SDK
- 与uniapp建立连接,引入hellouniapp.dcloud.net.cn/hybrid/html/uni.webview.1.5.5.js,可以下载到本地
调用api与小程序通信
new Vue({
el: '#app',
components: {
},
data () {
return {
urlParams: {
rooms: []
},
showRoomPopup: false
}
},
computed: {
},
created () {
},
watch: {
},
mounted () {
const { params } = this.urlToObj(location.href)
if (params) {
this.urlParams = JSON.parse(decodeURI(params))
}
document.addEventListener('UniAppJSBridgeReady', () => {
uni.getEnv((res) => {
console.log('当前环境:' + JSON.stringify(res));
});
})
},
methods: {
// url参数转对象
urlToObj (url) {
let obj = {};
if (url.indexOf('?') >= 0) {
let str = url.slice(url.indexOf('?') + 1);
let arr = str.split('&');
console.log(str, arr)
for (let j = arr.length, i = 0; i < j; i++) {
let arr_temp = arr[i].split('=');
obj[arr_temp[0]] = arr_temp[1];
}
}
return obj;
},
// 点击体验官带看
handleLook () {
// 跳转到小程序的某个页面
uni.navigateTo({
url: '/pages/vr/look'
});
},
// 点击看房型
handleRoom () {
console.log(this.urlParams)
this.showRoomPopup = true;
},
goRoom (url) {
// 跳转到小程序的某个页面
uni.navigateTo({
url: `/pages/vr/room?url=${url}`
});
},
// 点击咨询
handleAsk () {
// 发送消息给小程序
uni.postMessage({
data: {
action: '咨询'
}
});
// 因为网页向应用?postMessage?时,会在特定时机(后退、组件销毁、分享)触发并收到消息。 所以用uni.redirectTo触发小程序的重新加载实时接收消息
uni.redirectTo({
url: '/pages/vr/vr'
});
}
}
})
页面预览效果:
小提示:如何在开发者工具查看webiew页面的信息
小程序端代码参考
<template>
<web-view :src="vrUrl" @message="onMessage"></web-view>
</template>
<script>
import { callPhone } from '@/utils';
export default {
data() {
return {
vrUrl:
// 这里要换成你的在线网页地址,我这里写的是本地的
`http://127.0.0.1:5500/vr-demo/index.html?params=` +
encodeURI(
JSON.stringify({
rooms: [
{
name: '房间1',
url: 'https://www.realsee.com/website/customer/dataSpace/vr/kPJJK5rx',
},
{
name: '房间2',
url: 'https://www.realsee.com/website/customer/dataSpace/vr/kPJJK5rx',
},
],
})
),
};
},
onLoad(props) {
console.log(props);
},
methods: {
// 接收webview传来的消息
onMessage(e) {
const { data } = e.detail;
console.log(
data,
'web-view传来的信息,在小程序后退、组件销毁、分享会触发'
);
console.log(data.at(-1));
if (data?.at(-1)?.action === '咨询') {
callPhone('18205236589');
}
},
},
};
</script>