微信小程序中webView的H5页面与小程序双向通信,调用微信小程序预览文件功能

前言:

最近做的微信小程序项目,有个需求是:微信小程序中webView内嵌的H5页面中,有多种格式的文件(包括pdf、doc、Excel、mp4、png等)需要支持在微信小程序中打开预览。

一、项目需求简介

微信小程序项目中webView内嵌了一个H5页面,这个H5页面同时也内嵌在App应用(包括安卓和iOS)中,所以需要在H5页面中判断是否是在微信小程序中,只有在小程序中才触发这个传值交互。

H5页面中会展示文件目录,点击可以打开对应的文件。

所以,需要做到:如果在App中,则调用App原生的方法打开文件;如果在微信小程序中,需要调用小程序预览文件的功能。

二、微信小程序中webView的H5页面,并传值给H5

  1. 微信小程序中的入口页面,如下图:
wxml 复制代码
<view bindtap="toMaintenanceInfoPage" data-id="{{item.id}}" data-name="{{item.name}}" data-index="{{itemIndex}}" class="content">
js 复制代码
methods: {
// 跳转至详情
toMaintenanceInfoPage(e) {
  const data = e.currentTarget.dataset;
  app.globalData.maintenanceCenterIndex = e.currentTarget.dataset.index;
  const token = wx.getStorageSync('token');
  const url = api.nspUrl;
  wx.navigateTo({
    url: `/pages/webViewPage/webViewPage?url=${url}&token=${token}&id=${data.id}&name=${data.name}`,
  })
}
}
  1. 微信小程序中的webView页面,如下图:
wxml 复制代码
<view class="container">
  <web-view wx:if="{{url}}" src="{{url}}"></web-view>
</view>
js 复制代码
onLoad: function (options) {
    if (options.token) {
      this.setData({
        url: `${options.url}?token=${options.token}&id=${options.id}`,
        name: options.name,
        token: options.token,
        id: options.id,
      })
    }
},

这样就已经在微信小程序中完成了嵌套H5页面的功能。

三、点击H5页面中的文件,调用小程序原生预览文件功能

html 复制代码
<p class="title">内部资料</p>
<div class="dataList">
  <div v-for="(item, index) in detailData.knowledgeAttachmentList" :key="index" class="item">
    <span @click="toAppDownload(item)">{{item.name}}.{{item.attachmentSuffix}}</span>
  </div>
</div>

H5传值:

  1. 点击之后,H5判断是否是在微信小程序中,因为H5不止在小程序中嵌套,还可以在App中打开,或者可以单独在浏览器中打开,所以只有在小程序中才触发这个传值:
js 复制代码
// 判断是否在微信环境
const isWeixin = /MicroMessenger/i.test(navigator.userAgent);
// 判断是否在微信小程序环境
const isMiniProgram = /miniProgram/i.test(navigator.userAgent.toLowerCase());
  1. H5传值,需要实现H5页面跳转到小程序的某个页面,所以要先安装小程序的sdk,我这边是vue项目,安装步骤如下:
  • 先安装依赖
npm 复制代码
// 安装依赖
npm install weixin-js-sdk
  • 然后引入依赖
js 复制代码
// 引入依赖
import wx from 'weixin-js-sdk';
  • H5使用依赖进行跳转:从H5页面中获取文件的URL和文件name,然后跳转到指定的小程序页面,并将这俩参数传到小程序中。
js 复制代码
wx.miniProgram.navigateTo({
  url: `/pages/previewPage/previewPage?source=wap&url=${newUrl}&name=${name}`,
});

说明:

此处跳转到小程序页面的原因是:

  1. 我们后端返回的文件URL是华为云自动生成的,域名虽然是固定的,但是域名下没有对应的项目,所以没有办法在域名下放置微信小程序要求的配置文件。如果能放配置文件的域名,此处是可以直接跳转到webViewPage页面的。
  2. 没有用wx.miniProgram.postMessage({ data:postData });,是因为只有用户点击了小程序的后退、分享按钮或者是小程序嵌入的H5页面销毁才能触发参数的传递,否则不会触发。 显然这个接口满足不了我的需求。
    参考链接:web-view相关接口

四、微信小程序接收值

小程序previewPage页面接收值,并在onLoad时打开:

js 复制代码
onLoad: function (options) {
  if (options.source && options.source === 'wap') { // 如果是在小程序内打开文件
    this.wxDownLoad(options);
  }
},

如果文件类型为pdf、xlsx、doc等时的打开方式:

js 复制代码
wxDownLoad(options) {
    wx.showLoading({
      title: '正在打开...',
    });
    wx.downloadFile({
      url: options.url,
      filePath: wx.env.USER_DATA_PATH + "/" + decodeURIComponent(options.name), // 设置自定义标题
      success: (res) => {
        if (res.statusCode === 200) {
          const filePath = res.filePath;
          wx.openDocument({
            showMenu: true,
            filePath: filePath,
            success: function (res) {
              wx.hideLoading();
            },
            fail: function (res) {
            }
          })
        }
      },
    })
  }

如果文件类型是视频或图片(mp4/png、jpg等)时,需要判断文件后缀,做不同的操作:

js 复制代码
// 获取文件后缀
const suffix = options.url.substr(options.url.lastIndexOf("."));

if (suffix.indexOf('png') > -1 || suffix.indexOf('jpg') > -1 || suffix.indexOf('jpeg') > -1) {
  that.setData({ imgUrl: options.url });
} else if (suffix.indexOf('mp4') > -1) {
  that.setData({ videoUrl: options.url })
}
wxml 复制代码
<view class="container">
  <video wx:if="{{videoUrl}}" class="video" src="{{videoUrl}}" show-mute-btn="true" ></video>
  <image wx:elif="{{imgUrl}}" src="{{imgUrl}}" data-url="{{imgUrl}}" bindtap="fnPreviewImage" class="avatarImg" mode="widthFix"></image>
</view>

这样就实现了微信小程序与内嵌webView的H5页面的双向通信,并且也能在webview中预览各种格式的文件。

以上,希望对大家有帮助!

相关推荐
killerbasd10 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
大家的林语冰12 小时前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
M ? A14 小时前
Vue 迁移 React 实战:VuReact 一键自动化转换方案
前端·vue.js·经验分享·react.js·开源·自动化·vureact
Burt14 小时前
我的 2026 全栈选型:Vue3 + Elysia + Bun + AlovaJS
vue.js·全栈·bun
小锋java123414 小时前
SpringBoot 4 + Spring Security 7 + Vue3 前后端分离项目设计最佳实践
java·vue.js·spring boot
一 乐14 小时前
校园线上招聘|基于springboot + vue校园线上招聘系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·校园线上招聘系统
LanceJiang14 小时前
从输入 URL 到页面:一个 Vue 项目的“奇幻漂流”
vue.js
码喽7号15 小时前
vue学习四:Axios网络请求
前端·vue.js·学习
像素之间16 小时前
为什么运行时要加set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve
前端·javascript·vue.js
M ? A16 小时前
Vue转React实战:defineProps精准迁移实战
前端·javascript·vue.js·经验分享·react.js·开源·vureact