小程序与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;
}
相关推荐
m0_748255021 分钟前
前端常用算法集合
前端·算法
真的很上进15 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web1309332039821 分钟前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_23442 分钟前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1231 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~2 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语2 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg2 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww2 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest