小程序与webview互通

前言

最近遇到这么一个场景,需要在微信小程序里通过webview嵌入一个h5页面,h5页面需要传参给小程序,小程序收到参数后实时去做出某些行为,但是微信小程序是不支持webview和小程序双向通信的,只有规定的时机可以获取到收到额度参数,所以只能用比较取巧的方法

实现思路

webview跳转到小程序是通过路由跳转的,而且小程序里可以实时监听路由,那么就可以通过路由来传递参数

实现代码

html 复制代码
//webview.html

<!DOCTYPE html>
<html lang="en">
  <body>
    <div class="content-part">
      <button class="lkmeLogin">登录</button>
    </div>

    <script
      type="text/javascript"
      src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"
    ></script>
    <script>
      function jumpToMiniProgramPage(url) {
        wx.miniProgram.getEnv(function (res) {
          if (res.miniprogram) {
            var data = {id:1};
            var hashchangeFunc = (_) => {
              var { callback: result } = JSON.parse(
                location.hash.split("?")[1]
              );
                // 防止回调参数未取到
                try {
                  result = decodeURIComponent(result);
                  result = JSON.parse(result || "{}");
                } catch (e) {
                  result = {};
                }
                var { errNo, errMsg, res } = result;
                if (errNo >= 0) {
                  resolve(result);
                } else {
                  reject(result);
                }
                // 由于小程序改变了页面的hash,需要返回
                history.back();
                // 移除当前hashchange的监听
                window.removeEventListener("hashchange", hashchangeFunc);
            };
            let joiner = url.indexOf("?") < 0 ? "?" : "&";
            wx.miniProgram.navigateTo({
              url: `${url}${joiner}${'data=' +JSON.stringify(data)}`,
            });
            window.addEventListener("hashchange", hashchangeFunc);
          }
        });
      }

      $(".lkmeLogin").on("click", function () {
        var url = "/pages/pay/pay";
        let msg = `\r\n\r\n当前location.href值为: ${location.href}\r\n并且马上返回上级页面防止url污染`;
        jumpToMiniProgramPage(url)
          .then(({ errNo, errMsg, res }) => {
            alert(`获取成功: ${JSON.stringify(res)}` + msg);
          })
          .catch(({ errNo, errMsg, res }) => {
            alert(`获取失败: ${errMsg}` + msg);
          });
      });
    </script>
  </body>
</html>

小程序代码

js 复制代码
// pages/pay/pay.js
import {
  setPageCallBack
} from "../../utils/util.js";
const { oneKeyLogin } = requirePlugin("auth-plugin");

Page({
  /**
   * 页面的初始数据
   */
  data: {
    params: "", // webview带给当前页面的参数
    triggered: false, // 是否已触发回调的标记,在页面销毁时可判断是否执行回调
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    console.log(`webview传过来的入参:${JSON.stringify(options)}`);
      let {
      href,
      ...params
    } = JSON.parse(options.data);

    // url带过来的参数会被编码, 所以这里需要解码处理
    this.setData({
      href: decodeURIComponent(href),
      params,
      paramsToString: JSON.stringify(params)
    });

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {
    // 页面销毁, 还没执行过回调,默认失败
    if (!this.data.triggered) {
      setPageCallBack({
        href: this.data.href,
      });
    }
  },
});
js 复制代码
//util/util.js
/**
 * 描述: 设置 webview 页面操作完成给H5页面的回调事件, 并且返回webview页面
 * @param: data {Object} 参数
 * @param: callback {Object} 传给H5页面的参数
 */
export function setPageCallBack(
  data = {
    href: "",
  },
  callback = {
    errNo: -1,
    errMsg: "未执行回调直接返回",
    res: {},
  }
) {
  console.info("回调事件的参数", data);
  var pages = getCurrentPages();
  console.log("我是获取的pages栈----------------------", pages);
  var currPage = pages[pages.length - 1]; //当前页面
  //上一个页面 (index page)
  var prevPage = pages[pages.length - 2];
  let {
    href,
  } = data;
  let visitUrl = href+'#?'+ JSON.stringify({callback:callback});
  console.log(`设置webview的url为:${visitUrl}`);
  prevPage.setData({
    visitUrl,
  });
  // 关闭当前webview
  wx.navigateBack();
}

/**
 * 配置webview来源地址
 * @param {*} href webview的文件目录地址
 * @param {*} callback 回调给webview的callback字符串
 */
export function getWebviewHref(href,   callback) {
  // 取url的query参数
  // 单独处理hash的query参数
  let query = href.split("?")[1] ? JSON.parse(href.split("?")[1]) : {};
  if (typeof callback === "object") callback = JSON.stringify(callback);
  Object.assign(query, {
    callback,
  });
  // 防止当前webview的url不存在hash出错
  var hash =  "#";
  console.log(`callback:${callback}`);
  console.log(`query:${JSON.stringify(query)}`);
  if (JSON.stringify(query) !== "{}") {
    hash += "?" + JSON.stringify(query);
  }
  return href + hash;
}
相关推荐
道不尽世间的沧桑14 分钟前
第17篇:网络请求与Axios集成
开发语言·前端·javascript
diemeng11191 小时前
AI前端开发技能变革时代:效率与创新的新范式
前端·人工智能
bin91533 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
晴空万里藏片云5 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一5 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe
奶球不是球5 小时前
el-button按钮的loading状态设置
前端·javascript
kidding7235 小时前
前端VUE3的面试题
前端·typescript·compositionapi·fragment·teleport·suspense
Σίσυφος19007 小时前
halcon 条形码、二维码识别、opencv识别
前端·数据库
学代码的小前端7 小时前
0基础学前端-----CSS DAY13
前端·css
css趣多多8 小时前
案例自定义tabBar
前端