前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

微信h5网页跳转小程序方案 开放标签实战

首页2020-07-24 12:01:24Front-End
小程序微信JS-SDKH5

公众号里推了一个活动 H5,用户看完想下单,结果下单流程在小程序里。以前只能在页面上放一张小程序码,配一行「长按识别进入小程序」,用户长按、识别、确认,三步走完还得再找一遍商品。转化率什么样可想而知。

微信后来开放了一组开放标签,其中 wx-open-launch-weapp 就是专门解决这件事的,H5 上放一个按钮,点一下直接拉起指定小程序的指定页面。这篇把接入过程完整记一遍,从资格确认、JS-SDK 配置,到在 Vue 项目里的具体写法,再到版本判断和降级。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • 开放标签的主体资格和系统版本门槛,哪些账号根本接不了
  • 微信 JS-SDK 的两种引入方式,以及 openTagList 这个容易漏的字段
  • 在 Vue 项目里让自定义标签不报错的配置
  • 怎么判断微信版本,以及原文那段版本判断代码为什么是错的
  • 开放标签内部的样式限制和 username、path 两个参数的填法
  • launch 和 error 两个回调事件怎么用
  • 微信后台的配置路径这几年的变化,和相关的注意事项

# 一、先确认你有没有资格接

这一步别跳过,很多人代码写完了才发现账号根本用不了这个能力。

主体要求上,开放标签仅开放给已认证的服务号。订阅号不行,未认证的服务号也不行。如果你手上是个订阅号,到这里就可以停了,得先去做认证或者换主体。

系统要求上,微信版本要求为 7.0.12 及以上,系统版本要求为 iOS 10.3 及以上、Android 5.0 及以上。低于这个版本的客户端上,开放标签是渲染不出来的,页面上就是一片空白。

所以降级方案不是可选项,是必选项。

除了这两条硬门槛,还有两个前置动作要做:页面必须部署在公众号后台配置过的 JS 接口安全域名下,并且必须是 HTTPS。这两条不满足的话,wx.config 那一步就直接过不去。

# 二、接入微信JS-SDK

有两种引入方式,看你的项目是什么形态。

包使用方式,适合有构建流程的工程化项目:

"weixin-js-sdk": "^1.6.0"
@前端进阶之旅: 代码已经复制到剪贴板

直接在页面上使用,适合传统的多页项目。在需要调用 JS 接口的页面引入如下 JS 文件:http://res.wx.qq.com/open/js/jweixin-1.6.0.js,这个地址是支持 https 的。实际接入时请直接写 https,因为你的页面本来就必须是 HTTPS,混着引 HTTP 资源会被浏览器拦掉。

引入之后调 wx.config 注入配置:

wx.config({
  appId: '',
  debug: true,
  timestamp: '',
  nonceStr: '',
  signature: '',
  jsApiList: [],
  openTagList: ['wx-open-launch-app','wx-open-launch-weapp'] // 获取开放标签权限
});
@前端进阶之旅: 代码已经复制到剪贴板

这段配置里最容易漏的就是 openTagList。很多人照着普通 JS-SDK 的文档抄,只填了 jsApiList,然后发现按钮死活不出来。开放标签的权限和普通 JS 接口的权限是分开申请的,用到哪个标签就把哪个标签名写进 openTagList。

需要注意的点归纳成三条:

  • wx.config 内要列出使用到的 openTagList
  • 要符合开放平台列出的要求,见 https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_H5_Launch_APP.html
  • 如果你还要跳 App,App 端需要按文档接入微信 SDK,见 https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html

signature 那几个字段是后端算好返回给你的,不要在前端拼。签名的原始串里包含当前页面的 URL,这块的坑我在另一篇里写得比较细,可以对照着看: H5之微信公众号分享。

在微信开发者工具内打开你的网页测试,如果显示这样的返回,说明你已经接入 JS-SDK 成功了:

{errMsg: "config:ok"}
@前端进阶之旅: 代码已经复制到剪贴板

调试期间 debug: true 一定要开着,配置错了它会直接 alert 出具体原因,比自己猜快得多。上线前记得关掉。

# 三、在Vue中使用例子

下面这套是在 Vue 2 项目里的完整落地过程,分四步。

# 第1步 在main.js中设置

wx-open-launch-weapp 不是标准 HTML 元素,也不是 Vue 组件,Vue 在编译模板时碰到它会警告「未知的自定义元素」。所以要先告诉 Vue 忽略这几个标签:

// 忽略微信自定义标签
Vue.config.ignoredElements = ['wx-open-launch-weapp','wx-open-launch-app']
@前端进阶之旅: 代码已经复制到剪贴板

这行代码不写不会导致功能不可用,但控制台会一直刷警告。而且在某些构建配置下警告会被当成错误处理,直接把编译卡住。

# 第2步 获取微信版本

先判断是不是在微信环境里,再取版本号:

// 判断微信环境内
isWechat() {
  let ua = window.navigator.userAgent.toLowerCase()
  // console.log(ua)
  if (ua.match(/MicroMessenger/i)) {
    return true
  } else {
    return false
  }
},

// 获取微信版本
// return eg. 7.0.16.1600
getWeixinVersion() {
  return navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i)[1]
},
@前端进阶之旅: 代码已经复制到剪贴板

getWeixinVersion 里直接对 match 的结果取下标是有风险的,非微信环境下 match 返回 null,这句会直接抛错。原文用 isWechat() && getWeixinVersion() 的短路写法把它挡住了,逻辑上没问题,但如果这个函数被别处单独调用就会炸。稳妥的做法是在函数内部自己判空。

然后在 created 里做版本比较:

created(){
  // 微信版本号大于 7.0.12 开放标签才可进行
  const wxVersion = this.isWechat() && this.getWeixinVersion() || ''
  if(wxVersion){
    let v = wxVersion.split('.')
    if(v[0]>=7){
      if(v[1]>=0){
        if(v[2]>=12){
          this.enableLaunchWeapp = true
        }
      }
    }
  }
},
@前端进阶之旅: 代码已经复制到剪贴板

这段是原文的写法,我当时也是这么写的。但这里有个坑要注意,这个三层嵌套的判断是错的。

你想想看,微信版本走到 8.0.5 的时候会发生什么?v[0] 是 8,大于 7,进第一层;v[1] 是 0,进第二层;v[2] 是 5,小于 12,判断失败。结果一个明显比 7.0.12 新的版本被当成了低版本,开放标签被降级掉了。

版本号比较不能逐段独立判断,要按位比较并且高位分出胜负就立即返回。改成这样:

// 把版本号按段比较,高位一旦分出大小就返回,避免 8.0.5 被误判
function gteVersion(current, target) {
  const a = String(current).split('.').map(Number)
  const b = String(target).split('.').map(Number)
  const len = Math.max(a.length, b.length)
  for (let i = 0; i < len; i++) {
    const x = a[i] || 0
    const y = b[i] || 0
    if (x > y) return true
    if (x < y) return false
  }
  return true
}
@前端进阶之旅: 代码已经复制到剪贴板

调用起来就一行:

created(){
  const wxVersion = this.isWechat() ? this.getWeixinVersion() : ''
  this.enableLaunchWeapp = !!wxVersion && gteVersion(wxVersion, '7.0.12')
},
@前端进阶之旅: 代码已经复制到剪贴板

微信版本号有时候是四段的,比如注释里那个 7.0.16.1600,上面这个函数对段数不一致的情况也能正确处理,多出来的位按 0 补。

# 第3步 在页面上展示

如果微信版本低于 7.0.12,开放标签是无法使用的,需要降级处理。所以模板里用 enableLaunchWeapp 分了两个分支:

<div v-if="enableLaunchWeapp">
  <wx-open-launch-weapp
    id="launch-btn"
    username="gh_edc489d117fa3d"
    path="/pages/home/index.html"
  >
    <script type="text/wxtag-template">
      <style>
        .goodsname {
          font-size: 16px;
          color: #333333;
          font-weight: 600;
          line-height: 24px;
          margin-bottom: 5px;
        }
      </style>
      <h1 class="goodsname">{{ goodsInfo.goodsName }}</h1>
    </script>
  </wx-open-launch-weapp>
</div>
<h1 v-else>{{ goodsInfo.goodsName }}</h1>
@前端进阶之旅: 代码已经复制到剪贴板

上面 username 那个值是示例,换成你自己小程序的原始 ID。

这段模板里有四个点必须说清楚,每一个我都卡过:

  • 在 Vue 中需要用 text/wxtag-template 类型的脚本标签把内容包裹起来,否则按钮不能展示。这个标签不是真的脚本,微信会把它的内容当成模板取出来渲染到开放标签内部
  • username 为小程序原始 ID,以 gh_ 开头,需要在小程序后台的设置里获取。注意不是 AppID,这两个很容易搞混
  • path 是打开小程序的指定页面,需要加上 .html,比如 /pages/home/index.html
  • style 中的样式写法需要注意,goods-name 这种带连字符的类名好像不支持,需要写成 goodsname,而且只支持 px 格式

最后这条我排查了挺久。开放标签内部是一块独立的渲染区域,外面的 CSS 进不去,里面的样式只能写在这个模板里的 style 块中,而且支持的属性和写法都是受限的。rem、vw 这些相对单位不要用,直接写 px。带连字符的类名不生效这条是我实测的结论,不排除后来微信放开了限制,具体请以官方文档为准。

还有一个视觉上的坑。开放标签渲染出来的是一个透明的可点击区域,覆盖在你的模板内容上。你在外面给 wx-open-launch-weapp 设的宽高如果和内部模板对不上,就会出现「按钮看着在这里,点了没反应」或者「按钮外面一圈也能点」的情况。稳妥的做法是给外层容器和内部模板设一样的尺寸。

# 第4步 监听开放标签回调事件

开放标签会派发两个自定义事件,launch 表示跳转指令已经发出,error 表示跳转失败:

fe
  • 一、先确认你有没有资格接
  • 二、接入微信JS-SDK
  • 三、在Vue中使用例子
    • 第1步 在main.js中设置
    • 第2步 获取微信版本
    • 第3步 在页面上展示
    • 第4步 监听开放标签回调事件
  • 四、这几年变了什么
  • 五、几个常见问题的排查顺序
  • 总结
  • 参考

← Github Action 部署应用实战 工作流配置与四种上线方式小程序直播总结 live-pusher与live-player接入实践 →