开发 web-view 组件

收藏
我的收藏

简介

本教程将聚焦在如何接入web-view 网页容器

能力介绍

    承载网页的容器,会自动铺满整个小程序页面
    使用该组件要进行业务域名配置,仅支持添加开发者可控制(能放置校验文件到域名根目录)的域名
注意
个人类型的小程序暂不支持使用。

最终效果

学习内容

    1.如何在开发者平台控制台配置域名白名单。
    2.如何在项目中接入及调试 web-view 组件。

配置域名白名单

本页目标

可以在控制台配置对应的域名。

前置条件

账号拥有当前小程序的管理员或以上的权限,可以进行「编辑」、「添加」 和 「下载检验文件」等操作。

配置流程

    1.开发者登录开发者平台控制台,进入对应小程序。
    2.在左侧导航栏选择「开发」>「 开发配置」>「域名管理 」
    3.在当前页面往下拉,看到「域名管理 」。
    4.点击「下载校验文件」并放置到服务器。
    配置说明:
    假设:
    下载的文件名:pNWfyB8oLl.txt
    文件内容:4e056cd59ab2f40e3d6abc51b233e500
    判断生效方式:
    配置服务器如 Nginx ,使访问 https://example.com/pNWfyB8oLl.txt 直接返回 4e056cd59ab2f40e3d6abc51b233e500 即可。
    5.点击「编辑」或「添加」进行操作。对具体域名根目录配置完校验文件之后,就可以进行具体域名添加了。需要先确保当前登录控制台的账号有管理员或拥有者权限。
    6.添加具体的「域名」和「端口」。

配置规则

    这里的配置规则是 「域名 」「端口」全匹配。
    无需配置 HTTP 或者 HTTPS 协议。

端口配置相关实例

    不配置端口:
    https://server.com,那么请求的 URL 中也不能包含端口,甚至是默认的 443 端口也不可以。如果向 https://server.com:443 请求则会失败。
    配置端口:
    https://server.com:8080,但是配置后只能向 https://server.com:8080 发起请求。如果向 https://server.comhttps://server.com:9091等 URL 请求则会失败。
    多种诉求都考虑:
    如果有的 URL 请求上携带端口,有的不需要,那么就需要将所有的相关域名和端口一起配置到 web-view 域名中。如上图配置,在 web-view 容器中可以向 https://server.com:443https://server.com:8080https://server.com 三种成功发起 URL 请求。

web-view 域名名单生效范围

网页和网页内 iframe 的域名都生效。

接入 web-view 组件的基本能力

本页目标

能够实现基础的 web-view 组件,并能访问网页。

极简流程

    1.确认链接已经在控制台配置。
    2.代码实现。///请将src中的链接替换成自己的方案 <web-view src="https://m.toutiao.com/i6834015878997082632/"></web-view>
    3.代码调试。
    由于本地开发阶段通常是测试环境的 H5 地址,因此无法在后台配置校验文件。
    因此在 IDE 调试时,可以先开启“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书” 开关。保证 IDE 可以访问到测试环境 H5。
    在调试通过,H5 页面发布后,再关闭该开关进行线上测试。
    IDE 中打开 webview 组件调试面板。
    Webview 调试面板,支持元素选取,控制台输出,源代码调试等。

web-view 组件内使用其他能力

本页目标

能够实现在 web-view 组件内实现和小程序相关能力。

前置条件

H5 页面中引入抖音开放平台的 JSSDK。
<script src="https://lf1-cdn-tos.bytegoofy.com/goofy/developer/jssdk/jssdk-1.2.0.js"></script>

通信能力

在小程序后退、组件销毁、页面分享时,通过 bindmessage 发送给用户的能力。
    1.H5页面中调用tt.miniProgram.postMessage
<button onclick="postSomeMessage()">post some message</button>; function postSomeMessage() { tt.miniProgram.postMessage({ data: { random: Math.random().toString(36).slice(2), }, }); }
    2.小程序中声明bindmessage和具体方法。
<web-view src="https://some-domain/some/path/index.html" bindmessage="onMessage" ></web-view>
Page({ /** * 小程序后退、组件销毁、页面分享时且当前 H5 页面调用过 tt.miniProgram.postMessage,则触发此函数 * 其中 options.detail.data 就是 H5 页面通过 tt.miniProgram.postMessage 传入的 data 信息; */ onMessage(options) { /** * 网页的消息发出顺序为 postMessage1、postMessage2、postMessage3 * options.detail.data 的详细内容分别为: * [{ mes: "postMessage1" }, { mes: "postMessage2" }, { mes: "postMessage3" }] */ console.log("onmessage:", options.detail.data); }, });
    3.信息获取。
    小程序后退、组件销毁、页面分享时且当前 H5 页面调用过 tt.miniProgram.postMessage。则触发此函数 其中 options.detail.data 就是 H5 页面通过 tt.miniProgram.postMessage 传入的 data 信息。
    网页的消息发出顺序为 postMessage1、postMessage2、postMessage3 options.detail.data 的详细内容分别为: [{ mes: "postMessage1" }, { mes: "postMessage2" }, { mes: "postMessage3" }] 。

判断 H5 页面是否在小程序 web-view 打开

通过 UserAgent 进行判断。
// isTTWebView 若为 true,则是在头条小程序的 web-view 中打开 const isTTWebView = navigator.userAgent .toLowerCase() .includes("toutiaomicroapp");

分享时获取 URL

需要在小程序的页面对应的 JS 里实现 onShareAppMessage
Page({ onShareAppMessage(options) { console.log(options.webViewUrl); // 当前 web-view 的URL }, });

返回上一页

H5 页面中实现调用 tt.miniProgram.navigateBack。
<button onclick="navigateBack()">navigateBack</button>; function navigateBack() { tt.miniProgram.navigateBack({ delta: 1, }); }

二级页面侧滑返回示例

期望在 H5 的二级页面侧滑返回上级 h5 页面,而不是返回到小程序页面。
在 H5 页面中调用tt.miniProgram.setSwipeBackModeSync
tt.miniProgram.setSwipeBackModeSync(0);

checkJsApi 使用示例

使用 checkJsApi 判断抖音是否支持某些 API。
H5 页面中调用tt.miniProgram.checkJsApi
function checkJsApi() { tt.miniProgram.checkJsApi({ jsApiList: ["chooseImage", "previewImage", "compressImage", "uploadFile"], success(res) { console.log("checkJsApi success:", res); }, fail(res) { console.log("checkJsApi fail:", res); }, }); }

图片选择与上传

tt.miniProgram.chooseImage({ count:1, sourceType:'album', success(res){ console.log('chooseImage success:', res); tt.miniProgram.uploadFile({ url: 'https://some-domain/upload', filePath: res.tempFilePaths[0] name: 'data', success(res){ console.log('uploadFile success:', res); }, fail(res){ console.log('uploadFile fail:', res); } }) }, fail(res){ console.log('chooseImage fail:', res); } })

支付能力

web-view 组件中不支持调用 h5 中的支付,请跳转到小程序里支付,支付完成再返回 web-view 页面,逻辑如下:
    1.H5调用 tt.miniProgram.navigateTo 或 tt.miniProgram.redirectTo 跳转至小程序支付页面,小程序支付 API: tt.pay。
// webview.html(web-view 组件承载的网页地址) 中的跳转逻辑 tt.miniProgram.navigateTo({ url: "/pages/pay/index", success(res) { console.log("跳转成功", res); }, fail(err) { console.log("navigateTo调用失败", err); }, });
    2.支付页面完成支付后再跳转至 web-view 页面。
// pages/pay/index Page({ pay() { // 支付逻辑 ... // 支付完成 tt.navigateTo({ url: '/pages/webview/index', // 指定页面的 url }); }, });

Demo 工程

小程序工程

Node 服务端代码

const http = require("http"); const fs = require("fs"); const path = require("path"); // 定义HTML文件的文件夹路径 const publicDirectoryPath = path.join(__dirname, "demo"); http .createServer((req, res) => { // 假设所有请求的URL都能映射到一个实际的HTML文件 // 例如 /home 对应 public/home.html const requestedFile = req.url === "/" ? "/index" : req.url; const filePath = path.join(publicDirectoryPath, `${requestedFile}.html`); // 检查文件是否存在 fs.stat(filePath, (err, stats) => { if (err) { if (err.code === "ENOENT") { // No such file or directory res.writeHead(404, { "Content-Type": "text/plain" }); res.end(`404 file not found at ${req.url}`); } else { res.writeHead(500, { "Content-Type": "text/plain" }); res.end("500 Internal Server Error"); } } else if (stats.isFile()) { // 返回HTML文件 fs.createReadStream(filePath).pipe(res); } }); }) .listen(3000, () => console.log("Server is running on port 3000"));

H5 代码

Node 服务端同级目录下的 demo/index.html 文件。
<html lang="en"> <head> <meta charset="utf-8" /> <title>web-view demo</title> <script src=""></script> </head> <body> <button onclick="navigateBack()">navigateBack</button> <button onclick="postSomeMessage()">post some message</button> <button onclick="navigateToQuery()">navigate to Query Page</button> <button onclick="reLaunch()">re-launch</button> <button onclick="redirectTo()">redirect to</button> <button onclick="switchTab()">switch tab</button> <button onclick="chooseImage()">choose Image</button> <button onclick="checkJsApi()">checkJsApi</button> <button onclick="checkENV()">checkENV</button> </body> <script type="text/javascript"> function checkENV() { const isTTWebView = navigator.userAgent.toLowerCase().includes("toutiaomicroapp"); if (isTTWebView) { console.log("是"); } else { console.log("不是"); } } function navigateBack() { tt.miniProgram.navigateBack({ delta: 1, }); } function postSomeMessage() { tt.miniProgram.postMessage({ data: { random: Math.random().toString(36).slice(2), }, }); } function navigateToQuery() { tt.miniProgram.navigateTo({ url: '/pages/query/query?from=h5navigate', success(data){ console.log(data); }, fail(err){ console.log(err); } }); } function reLaunch() { tt.miniProgram.reLaunch({ url: '/pages/query/query?from=reLaunch', success(data){ console.log(data); }, fail(err){ console.log(err); } }); } function redirectTo() { tt.miniProgram.redirectTo({ url: '/pages/query/query?from=redirect', success(data){ console.log(data); }, fail(err){ console.log(err); } }) } function switchTab() { tt.miniProgram.switchTab({ url: '/pages/tab/tab', success(data){ console.log(data); }, fail(err){ console.log(err); } }) } function chooseImage() { tt.miniProgram.chooseImage({ count:1, sourceType:'album', success(res){ console.log('chooseImage success:', res); tt.miniProgram.uploadFile({ url: 'https://some-domain/upload', filePath: res.tempFilePaths[0] name: 'data', success(res){ console.log('uploadFile success:', res); }, fail(res){ console.log('uploadFile fail:', res); } }) }, fail(res){ console.log('chooseImage fail:', res); } }) } function checkJsApi() { tt.miniProgram.checkJsApi({ jsApiList: ["chooseImage", "previewImage", "compressImage", "uploadFile"], success(res) { console.log("checkJsApi success:", res); }, fail(res) { console.log("checkJsApi fail:", res); }, }); } </script> </html>

总结

恭喜,你已经完成了 web-view 组件的接入教程。
你在该 Codelab 中了解了:
    1.如何在开发者平台控制台配置域名白名单。
    2.如何在项目中接入及调试 web-view 组件。

更多 Codelab

如果想了解更多 Codelabs,请返回 Codelabs