QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

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

  • 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:073552

评论

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

如何在云中构建数字核心

云计算

百度大脑3月新品推荐:EasyDL视频目标追踪全新发布

百度大脑

百度大脑 EasyDL

翻译:《实用的Python编程》09_03_Distribution

codists

Python

Flink中的状态编程

大数据技术指南

flink 4月日更

知乎万赞回答:程序员面试为什么被要求造航母,而工作拧螺丝?

Java架构师迁哥

方寸之间,书写天地

石云升

4月日更 1 周年盛典 我和写作平台的故事 InfoQ 写作平台 1 周年

这个GItHub上的Java项目开源了 2021最全的Java架构面试复习指南

比伯

Java 编程 架构 面试 程序人生

计算机原理学习笔记 Day10

穿过生命散发芬芳

计算机原理 4月日更

趣题与算法(1)

阳龙生

简单了解InnoDB底层原理

leonsh

MySQL 数据库 innodb

浅谈JVM和垃圾回收

leonsh

Java JVM JVM虚拟机原理 垃圾回收算法

架构思维

无心

架构

架构实战营模块1作业指导

华仔

#架构实战营

Linux free 命令

一个大红包

linux命令 4月日更

最新分享:如何避免线程安全的坑?看这一篇就够了

学Java关注我

Java 编程 程序员 架构 计算机

融合趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Apache Flink

flink

不为人知的网络编程(十二):彻底搞懂TCP协议层的KeepAlive保活机制

JackJiang

TCP 即时通讯 IM

GitHub面试题库+阿里巴巴2021年Java岗面试26大核心专题,成功助我砍下7家大厂Offer

Java架构追梦

Java 阿里巴巴 架构 面试

欢迎参与 KubeVela 官方文档翻译活动

阿里巴巴云原生

容器 云原生 开发工具 OAM 资源调度

推进智慧城市建设 博睿数据亮相长三角城市数字化转型高峰论坛

博睿数据

数字化转型高峰论坛

使用Agora SDK开发React Native视频通话App

声网

RTC React Native 声网 RTE

华为云AI论文精读会2021第一期:高效语义分割模型Fast-SCNN分享

华为云开发者联盟

AI 华为云

如何提高Linux水平

cdhqyj

未来已来,HarmonyOS 开发者日全记录

清秋

华为 开发 物联网 新闻 HarmonyOS

架构实战营作业2

冷酷小绵羊

【全球年青人召集令】Hello World,Hello 2050

阿里巴巴云原生

容器 开发者 云原生 活动

深入理解Java虚拟机-HotSpot

华章IT

Java JVM 虚拟机

浅谈在探索数分之路上的“数据思维”论述

小飞象@木木自由

数据分析 数据分析体系 数据思维 数据分析方法论

那些打不垮你的,终究使你更强大

小天同学

读书 励志 个人感悟 4月日更

Flink的基石

五分钟学大数据

flink 4月日更

开源 1 年半 star 破 1.2 万的 Dapr 是如何在阿里落地的?

阿里巴巴云原生

Java 微服务 云原生 中间件 API

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