小程序与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;
}
相关推荐
前端李易安2 小时前
Web常见的攻击方式及防御方法
前端
PythonFun2 小时前
Python技巧:如何避免数据输入类型错误
前端·python
hakesashou2 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆2 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF2 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi2 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi3 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript
凌云行者3 小时前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻3 小时前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江3 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js