使用uniapp开发app时少不了需要打开h5页面这种需求。然而有些需求就很奇葩,让人头大。

简介

本文使用两种方法来实现uniapp webview和H5相互通讯。

  1. webview组件
  2. plus.webview

!!!不包含nvue的使用

一、webview组件

webview组件使用方法官网open in new window较为详细

1.app发送消息,h5接收

<!-- app -->
<template>
    <web-view :src="url" />
</template>

<script>
export default {
    data() {
        return {
            url: null,
        }
    },
    onLoad() {
        // 这里的setTimeout 仅作测试使用
        setTimeout(() => {
            var currentWebview = this.$scope.$getAppWebview()
            const vw = currentWebview.children()[0]

            vw.evalJS(`document.body.innerHTML = '修改body内容'`)

            vw.evalJS(`window.changeColor('#ccc')`)
        }, 1000 * 3)
    }
}
</script>
<!-- h5 -->
<!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>Document</title>
</head>
<body>
    123131
</body>
<script>
    function changeColor(color) {
        // 修改body 字体颜色
        document.body.style.color = color
    }
</script>
</html>

2.h5发送消息,app接收

<!-- h5 -->
<!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>Document</title>
    <!-- 官方的sdk -->
    <!-- 需要把 uni.webview.1.5.4.js 下载到自己的服务器 -->
    <script src="https://gitee.com/dcloud/uni-app/raw/dev/dist/uni.webview.1.5.4.js"></script>
</head>
<body>
    123131
</body>
<script>
    function sendMsg() {
        uni.postMessage({
            data: {
                action: {
                    type: '消息类型',
                    value: '消息内容',
                }
            }
        })
    }
    // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
    document.addEventListener('UniAppJSBridgeReady', function() {
        sendMsg()
    })
</script>
<!-- app -->
<template>
    <web-view :src="url"  @message="recvMsg" />
</template>

<script>
export default {
    data() {
        return {
            url: null,
        }
    },
    methods: {
        recvMsg(event) {
            // event数据结构
            // {
            //     "type": "message",
            //     "target": {},
            //     "currentTarget": {},
            //     "timeStamp": 1658216639367,
            //     "detail": {
            //         "data": [{
            //             "action": {
            //                 "value": "消息内容",
            //                 "type": "消息类型"
            //             }
            //         }]
            //     }
            // }
            console.log('h5发来的消息', event)
        }
    }
}
</script>

二、plus.webview

plus.webview文档地址open in new window

1.app发送消息,h5接收

<!-- app -->
<template>
    <view></view>
</template>

<script>
export default {
    data() {
        return {
            url: null,
        }
    },
    methods: {
        createWebView() {
            const sys = uni.getSystemInfoSync()
            const VW = plus.webview.create(this.url, 'custom-webview', {
                plusrequire: 'none', //禁止远程网页使用plus的API,有些使用mui制作的网页可能会监听plus.key,造成关闭页面混乱,可以通过这种方式禁止
                // 'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
                top: sys.statusBarHeight + 200, //放置在titleNView下方。如果还想在webview上方加个地址栏的什么的,可以继续降低TOP值
                // 设备高度 - 状态栏高度 - 自定义高度
                height: sys.screenHeight - sys.statusBarHeight - 200,
            })

            VW.addEventListener('loaded', () => {
                VW.evalJS(`window.changeColor('#ccc')`)
            })
            
            currentWebview.append(VW)
        }
    }
}
</script>
<!-- h5 -->
<!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>Document</title>
</head>
<body>
    123131
</body>
<script>
    function changeColor(color) {
        // 修改body 字体颜色
        document.body.style.color = color
    }
</script>
</html>

2.h5发送消息,app接收

<!-- h5 -->
<!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>Document</title>
</head>
<body>
    123131
</body>
<script>
    function changeTitle(title) {
        // 修改body 字体颜色
        document.title = title
    }
    setTimeout(() => {
        changeTitle('修改title触发webview的回调')
    }, 1000 * 3)
</script>
</html>
<!-- app -->
<template>
    <view>测试webview</view>
</template>

<script>
export default {
    data() {
        return {
            url: null,
        }
    },
    methods: {
        createWebView() {
            const sys = uni.getSystemInfoSync()
            const VW = plus.webview.create(this.url, 'custom-webview', {
                plusrequire: 'none', //禁止远程网页使用plus的API,有些使用mui制作的网页可能会监听plus.key,造成关闭页面混乱,可以通过这种方式禁止
                // 'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
                top: sys.statusBarHeight + 200, //放置在titleNView下方。如果还想在webview上方加个地址栏的什么的,可以继续降低TOP值
                // 设备高度 - 状态栏高度 - 自定义高度
                height: sys.screenHeight - sys.statusBarHeight - 200,
            })

            // 监听h5的标题变化, 页面加载完也会触发
            // 一种骚操作
            VW.addEventListener("titleUpdate", (event) => {
                // event 数据结构
                // {
                //     "title": "修改title触发webview的回调",
                //     "target": {
                //         "__view_array__": [],
                //         "__IDENTITY__": "NWindow",
                //         "__uuid__": "NWindow151658284135530",
                //         "__callbacks__": {
                //             "titleUpdate": ["function() { [native code] }"]
                //         },
                //         "__callback_id__": "plus161658284135530",
                //         "id": "custom-webview"
                //     }
                // }
                console.log('h5消息', event)
            })

            currentWebview.append(VW)
        }
    }
}
</script>

webview组件和plus.webview的差异

  • webview组件

    1. 打开一个新的app页面加载h5
    2. 不能自定义窗口大小、
    3. 用户需要进入一个webview页面
  • plus.webview

    1. 可以在当前页面打开,可以用于咨询人工等业务
    2. 可以自定义窗口大小,在当前页面打开一个占半屏的h5页面
    3. 用户还在当前页面

本文使用最小示例来展示