限时领|《AI 百问百答》专栏课+实体书(包邮)! 了解详情
写点什么

微信小程序转发朋友圈详解

  • 2020-09-28
  • 本文字数:3026 字

    阅读完需:约 10 分钟

微信小程序转发朋友圈详解

在 2020 年 7 月 7 日微信小程序低调的开放了一个功能,微信小程序“分享到朋友圈”。最近被产品提了相关需求,过程中遇到了一些坑。作者带着踩坑经验,给大家介绍下这个功能,以及其如何实现。

概述

点击右上角分享朋友圈

分享到朋友圈样式

朋友圈打开样式


这个功能目前只支持 Android(在 IOS 高版本微信支持朋友圈打开小程序能力,但不能分享)。


用户打开朋友圈分享的小程序,看到不是真正的小程序,而是原本页面的“单页模式”。

什么是“单页模式”?

以下是微信官方对于“单页模式”的描述:


“单页模式”下,页面顶部固定有导航栏,标题显示为当前页面 JSON 配置的标题。底部固定有操作栏,点击操作栏的“前往小程序”可打开小程序的当前页面。顶部导航栏与底部操作栏均不支持自定义样式。

“单页模式”默认运行的是小程序页面内容,但由于页面固定有顶部导航栏与底部操作栏,很可能会影响小程序页面的布局。因此,请开发者特别注意适配“单页模式”的页面交互,以实现流畅完整的交互体验。

限制

另外,“单页模式”存在着很多限制。以下是官方给出的禁用能力列表:



限制主要包括以下几点:


  1. 页面无登录态,与登录相关的接口,如 wx.login 均不可用

  2. 不允许跳转到其它页面,包括任何跳小程序页面、跳其它小程序、跳微信原生页面

  3. 若页面包含 tabBar,tabBar 不会渲染,包括自定义 tabBar

  4. 本地存储与小程序普通模式不共用


这些限制,让 “单页模式”只适用于内容展示,不适用于有较多交互

配置

针对“单页模式”,新增了单页模式相关配置。目前这个配置里只有一个 navigationBarFit 属性:



navigationBarFit 属性主要是针对原页面设置了 自定义导航栏 的情况。也就是原页面的 json 文件中配置了这个属性:


{  // ...  "navigationStyle":"custom"  // ...}
复制代码


给大家看一下普通导航栏和自定义导航栏的区别,下图是普通导航栏页面:



下图是自定义导航栏页面,我们在原本的导航栏位置使用了 banner:



"navigationStyle":"custom"这个设置在“单页模式”下也会生效。前文微信官方对“单页模式”的描述有说到“顶部导航栏与底部操作栏均不支持自定义样式”。如果我们在原页面设置了自定义导航栏。那么“单页模式”样式就会变成这样:



通过设置 navigationBarFit 为 squeezed就可以解决这个问题:


{  // ...  "singlePage": {    "navigationBarFit": "squeezed"  }  // ...}
复制代码


设置后的样式:



开发


接下来介绍如何在小程序中实现这个功能。


第一步在需要转发朋友圈的页面中注册用户点击右上角转发功能,这是实现转发朋友圈功能的必要满足条件。


onShareAppMessage: function () {  return {    title: '转发标题',    path: '/pages/home/index',    imageUrl: '自定义图片路径'  }}
复制代码


第二步注册分享朋友圈功能(从基础库 2.11.3 开始支持):


onShareTimeline: function () {  return {    title: '转发标题',    query: 'from=pyq',    imageUrl: '自定义图片路径'  }}
复制代码


注意,这里有个问题,分享朋友圈功能不支持自定义页面路径,意味着 只能转发当前页面 。如果当前页面存在较多“单页模式”限制功能,就可能让我们的页面不能按预期展示。


当页面存在限制功能时,我们存在两个方案,第一个方案,针对“单页模式”做改动,不调用那些限制的功能。第二个方案,另外写一个针对“单页模式”的页面。


这两种方案都需要能判断当前是否正处在小程序“单页模式”。


我们通过判断场景值(场景值用来描述用户进入小程序的路径)是否等于 1154 来判断当前是否正处在小程序“单页模式”。场景值可以在 ApponLaunch 获取。


// app.js
App({ // ... onLaunch(options) { const { scene } = options; this.isSinglePage = scene === 1154; } // ...})
复制代码


我们将是否正处在“单页模式”的 Boolean 值放入 App 实例,方便全局拿到值。


接下来说说两种方案。


第一种方案,在“单页模式”不调用那些限制功能(这是一种不推荐的方案,代码耦合性太强)。举个例子:


const app = getApp();
Page({ // ... onLoad() { if (!app.isSinglePage) { wx.login({ // ... }) } } // ...})
复制代码


第二种方案,针对“单页模式”另写一个页面。因为分享朋友圈功能并不支持自定义页面路径,我们只能另外写一个组件来作为“单页模式”的内容承载。


将 isSinglePage 放入页面的初始数据,方便在 wxml 中拿到:


// pages/home/index.js
const app = getApp();
Page({ data: { isSinglePage: app.isSinglePage, } // ...})
复制代码


home-single-page 就是分享到朋友圈的内容承载组件:


// pages/home/index.json{  // ...  "usingComponents": {    "home-single-page": "components/home-single-page/index"  },}  
复制代码


当“单页模式”时,我们展示 home-single-page组件,否则就展示普通页面内容:


// pages/home/index.wxml
<home-single-page wx:if="{{ isSinglePage }}" /><view wx:else> <!-- 普通页面内容 --></view>
复制代码


样式上虽然搞定了,但是在原本的生命周期中可能会调用一些限制功能,或者跑一些其它“单页模式”用不上的内容。我们得停止原本生命周期函数调用。


建议对传入 Page 的对象进行统一处理,当“单页模式”时,不调用原本的生命周期:


// pages/home/index.jsimport ExtendPage from 'common/extend-page/index'
const app = getApp();
ExtendPage({ data: { isSinglePage: app.isSinglePage, } // ...})
复制代码


ExtendPage 函数针对“单页模式”进行统一处理:


// common/extend-page/index.js
const app = getApp();
const PAGE_LIFE = [ 'onLoad', 'onReady', 'onShow', 'onHide', 'onError', 'onUnload', 'onResize', 'onPullDownRefresh', 'onReachBottom', 'onPageScroll'];
export default function(option) { let newOption = {};
if(app.isSinglePage) { newOption = PAGE_LIFE.reduce((res, lifeKey) => { if (option[lifeKey]) { res[lifeKey] = undefined; } return res; }, {}) }
return Page({ ...option, ...newOption, });}
复制代码


在“单页模式”下,我们将原本的生命周期都停止了调用。这样就能很好的将“单页模式”下的页面和普通页面进行解耦。


如果”单页模式“页面比较复杂,需要使用生命周期。我们也可以添加 singlePageLife属性,当处在“单页模式”下,就调用 singlePageLife内的生命周期:


// pages/home/index.jsimport ExtendPage from 'common/extend-page/index'
const app = getApp();
ExtendPage({ data: { isSinglePage: app.isSinglePage, }, singlePageLife: { onLoad() { // ... }, } // ...})
复制代码


// common/extend-page/index.jsconst app = getApp();
const PAGE_LIFE = [ 'onLoad', 'onReady', 'onShow', 'onHide', 'onError', 'onUnload', 'onResize', 'onPullDownRefresh', 'onReachBottom', 'onPageScroll'];
export default function(option) { let newOption = {};
if(app.isSinglePage) { const { singlePageLife } = option; newOption = PAGE_LIFE.reduce((res, lifeKey) => { if (singlePageLife[lifeKey]) { res[lifeKey] = singlePageLife[lifeKey]; } else if(option[lifeKey]) { res[lifeKey] = undefined; } return res; }, {}) }
return Page({ ...option, ...newOption, });}
复制代码


文章如有疏漏、错误欢迎批评指正。


本文转载自公众号有赞 coder(ID:youzan_coder)。


原文链接


微信小程序转发朋友圈详解


2020-09-28 14:073712

评论

发布
暂无评论
发现更多内容

2021金三银四最新拼多多 +蚂蚁金服 +头条(已拿offer),面试真题分享!

Java 编程 程序员 架构 面试

系统高可用之健康检查和健康度量那些事

vivo互联网技术

高可用 服务器

聚力边缘计算 共建数字中国丨浪潮边缘云ICP Edge 2.0 全新发布

聪明人的训练(二十六)

Changing Lin

4月日更

金三银四 Java 架构面试指南上线, 1000 余道大厂面试真题,送你上岸

Java 编程 程序员 架构 面试

网络协议学习笔记 Day5

穿过生命散发芬芳

网络协议 4月日更

RocketMQ 在使用上的一些排坑和优化

AI乔治

Java 架构 分布式 RocketMQ 高并发

分布式消息中间件(2):Kafka系统学习—集群搭建与使用、副本机制和实时日志统计流程

北游学Java

Java kafka 分布式 中间件

IT 专业的高校大学生编程技能及就业问卷调研

Yano

问卷调查

【死磕JVM】什么是JVM调优?

牧小农

JVM jvm调优 JVM基础

怎么理解组织?

石云升

团队建设 28天写作 职场经验 管理经验 4月日更

Android 关于CPU类型的so文件兼容问题(ABI)

寻找生命中的美好

android native so库 abi so文件

合作伙伴眼中的鸿蒙,专访海雀科技研发总监李尹

Geek_283163

Linux字符截取命令-cut

进击的梦清

Linux 运维 xshell

linux高性能服务器编程--高性能服务器程序框架

赖猫

Linux 服务器开发 高性能服务器 C/C++后端

分布式消息中间件(1):Rabbitmq入门到高可用实战!学会了这个还怕被B站面试官看不起?

北游学Java

Java 分布式 RabbitMQ 中间件

xch挖矿APP开发|xch挖矿系统软件开发

系统开发

容器 & 服务: 扩容(二)

程序员架构进阶

容器 k8s 28天写作 弹性扩容 4月日更

刹车失灵,数据的刹车是否也会失灵?

BinTools图尔兹

数据库 运维 dba 数据库管理工具

近期值得关注的四款工具

彭宏豪95

效率 工具 Mac 4月日更

Substrate 合约书之合约语言框架

Patract

rust Substrate polkadot Patract Wasm

chia奇亚挖矿软件开发|chia奇亚挖矿APP系统开发

系统开发

贝壳基于 Flink 的实时计算演进之路

Apache Flink

flink

MySQL 死锁套路:一次诡异的批量插入死锁问题分析

AI乔治

Java MySQL 架构

数据驱动的元数据组件

鲸品堂

方法论 架构设计原则 架构设计实战 数据分析方法论

2021团体程序设计天梯赛-部分题解

玄兴梦影

算法 比赛 算法解析

教育是限制吗?

箭上有毒

4月日更

JVM类加载机制笔记

风翱

4月日更 JVM类加载

chia奇亚分币软件开发|chia奇亚分币APP系统开发

系统开发

阿里P8独家揭秘:短期内升职加薪的方法,到底是什么?

Java架构师迁哥

基于MySQL存储的自研消息队列架构设计文档

Geek_2e7dd7

微信小程序转发朋友圈详解_小程序_郝加升_InfoQ精选文章