共计 7248 个字符,预计需要花费 19 分钟才能阅读完成。
前提须知
笔者公司的我的项目在微信端的功能定位为根底性能交易及服务,告诉用户交易揭示、交易流水等,而 APP 为次要的交易性能。之前是在多个页面有引流按钮跳转至 App,性能点比拟粗犷,间接 location.href = 利用宝链接
。当初产品有需要,说要用微信提供的标签来唤起 App
需要点:
所有跳转至 App 下载页面的局部,改成
Demo 后行
遇事不决,官网文档。查看后与微信 JS-SDK 性能点很像,这里我不废话,间接跳过。依照官网 demo,把示例写进业务代码中
import React, {useEffect, useRef} from 'react'; | |
import {toDownloadApp, isWechat, getWeixinVersion} from 'utils'; | |
const Download = () => {const wxRef = useRef(null) | |
useEffect(() => {if (wxRef.current) { | |
// @ts-ignore | |
wxRef.current?.addEventListener('launch', function (e: any) {console.log('success'); | |
}); | |
// @ts-ignore | |
wxRef.current.addEventListener('error', function (e) {console.log('fail', e.detail); | |
toDownloadApp()}); | |
} | |
}, []) | |
const onHandleClick = () => {toDownloadApp() | |
} | |
return (<div className="Download" onClick={onHandleClick}> | |
{/* @ts-ignore */} | |
<wx-open-launch-app | |
ref={wxRef} | |
appid="XXXX" | |
> | |
<script type='text/wxtag-template'> | |
<button>App 内查看 </button> | |
</script> | |
{/* @ts-ignore */} | |
</wx-open-launch-app> | |
</div> | |
) | |
} | |
export default React.memo(Download); |
测试胜利,demo 能跑通
组件试点
当初搞业务,以这个组件(Download)为试点开展,我要点击页面顶部的卡片(多个中央应用,抽离成 Download 组件),让其唤起 App,然而要判断其版本,如果版本过低,让其跳转至利用宝
import React, {useState, useEffect, useRef} from 'react'; | |
import LogoImg from '@/assets/images/logo.png'; | |
import {toDownloadApp, isWechat, getWeixinVersion} from 'utils'; | |
const Download = () => {const wxRef = useRef(null) | |
const [enableLaunchWeapp, setEnableLaunchWeapp] = useState(false); | |
useEffect(() => {const wxVersion = isWechat() && getWeixinVersion() || '' | |
if (wxVersion) {let v = wxVersion.split('.') | |
if (Number(v[0]) >= 7) {if (Number(v[1]) >= 0) {if (Number(v[2]) >= 12) {setEnableLaunchWeapp(true) | |
} | |
} | |
} | |
} | |
if (wxRef.current) { | |
// @ts-ignore | |
wxRef.current?.addEventListener('launch', function (e: any) {console.log('success'); | |
}); | |
// @ts-ignore | |
wxRef.current.addEventListener('error', function (e) {console.log('fail', e.detail); | |
toDownloadApp()}); | |
} | |
}, []) | |
const onHandleClick = () => {if (!enableLaunchWeapp) {toDownloadApp() | |
} | |
} | |
return (<div className="Download" onClick={onHandleClick}> | |
<div className="Download__logo"> | |
<img src={LogoImg} alt="logo" /> | |
</div> | |
<div className="Download__content"> | |
<div className="Download__content-title"> 雅美 App</div> | |
<div className="Download__content-desc"> 长泽雅美服务专区 </div> | |
</div> | |
{/* <div>1</div> */} | |
<div className="Download__btn"> 立刻关上 </div> | |
{/* @ts-ignore */} | |
<wx-open-launch-app | |
ref={wxRef} | |
appid="XXXXX" | |
style={{position: 'fixed', top: 0, left: 0, width: '100%', height: '60px', opacity: 0.3, background: 'blue'}} | |
> | |
<script type='text/wxtag-template'> | |
<div style={{position: 'fixed', top: 0, left: 0, width: '90%', height: '100%', opacity: 0.3, background: 'red'}} /> | |
</script> | |
{/* @ts-ignore */} | |
</wx-open-launch-app> | |
</div> | |
) | |
} | |
export default React.memo(Download); |
成果如下所示:
思路逻辑参考:wx-open-launch-weapp 款式问题,我也给它配上色彩,不便后续察看
测试同步,能点击卡片跳转,好,下一步,在所有须要点击跳转页面的中央退出相似这样的代码
<wx-open-launch-app | |
ref={wxRef} | |
appid="XXXX" | |
style={{position: 'fixed', top: 0, left: 0, width: '100%', height: '60px', opacity: 0.3, background: 'blue'}} | |
> | |
<script type='text/wxtag-template'> | |
<div style={{position: 'fixed', top: 0, left: 0, width: '90%', height: '100%', opacity: 0.3, background: 'red'}} /> | |
</script> | |
{/* @ts-ignore */} | |
</wx-open-launch-app> |
封装组件 WxOpenLaunchApp
如果是这样,就能够将其封装成一个组件了,起个名吧:WxOpenLaunchApp
将唤起 App 的内容包装成一个组件,暴雷 children 和 style 两个 props,代码如下:
import React, {useEffect, useRef, forwardRef} from 'react'; | |
import {toDownloadApp} from 'utils'; | |
export interface WxOpenLaunchAppProps { | |
children: React.ReactNode; | |
style?: React.CSSProperties; | |
} | |
const WxOpenLaunchApp: React.FC<WxOpenLaunchAppProps> = props => {const { style, children} = props; | |
const wxRef = useRef(null) | |
useEffect(() => {if (wxRef.current) { | |
// @ts-ignore | |
wxRef.current?.addEventListener('launch', function (e: any) {console.log('success'); | |
}); | |
// @ts-ignore | |
wxRef.current.addEventListener('error', function (e) {console.log('fail', e.detail); | |
toDownloadApp()}); | |
} | |
}, []) | |
return ( | |
<div className="wx-open-launch-app"> | |
{/* @ts-ignore */} | |
<wx-open-launch-app | |
ref={wxRef} | |
appid="XXXX" | |
style={style} | |
> | |
<script type='text/wxtag-template'> | |
{children} | |
</script> | |
{/* @ts-ignore */} | |
</wx-open-launch-app> | |
</div> | |
) | |
} | |
export default React.memo(WxOpenLaunchApp); |
那么 Download 组件也就能够洁净很多
... | |
const Download = () => { | |
... | |
return ( | |
... | |
<div className="Download__btn"> 立刻关上 </div> | |
{/* @ts-ignore */} | |
<WxOpenLaunchApp style={{position: 'fixed', top: 0, left: 0, width: '100%', height: '60px', opacity: 0.3, background: 'blue'}}> | |
<div style={{position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', opacity: 0.3, background: 'red'}} /> | |
</WxOpenLaunchApp> | |
... | |
) | |
} | |
... |
业务组件 OpenAppPopup
回到需要点,每个点击的中央都要弹出弹出框,点击 关上 App
,再唤起 App,这样的话,弹出框 + WxOpenLaunchApp 就能够联合成一个组件,放进去供页面调用,名字就叫 OpenAppPopup
,代码如下:
import React, {FC} from 'react'; | |
import {Popup, WxOpenLaunchApp, Toast} from 'components'; // 此乃公司自研组件库 | |
export interface OpenAppPopupProps { | |
show: boolean; | |
onCancel: () => void; | |
onSubmit: () => void;} | |
const OpenAppPopup: FC<OpenAppPopupProps> = (props) => {const { show, onCancel, onSubmit} = props; | |
return (<Popup.Group show={show}> | |
<Popup.Confirm | |
title="道歉,此性能需在雅美 App 中应用" | |
btnSubmitText={<div style={{ position: 'relative'}}> | |
关上 App | |
<WxOpenLaunchApp style={{position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', opacity: 0.3, background: 'blue'}}> | |
<div style={{position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', opacity: 0.6, background: 'red'}} /> | |
</WxOpenLaunchApp> | |
</div> | |
} | |
onCancel={onCancel} | |
onSubmit={onSubmit} | |
/> | |
</Popup.Group> | |
) | |
} | |
export default React.memo(OpenAppPopup); |
示意图如下:
接着在所有有跳转 App 的页面上用上这块逻辑即可
封装 HOOK
每个页面点击相似 下载 App
按钮时,会弹出 OpenAppPopup
,点击 关上 App
,须要判断你的微信版本,是否达到 7.0.12,如果每个页面都要加上这段
const wxVersion = (isWechat() && getWeixinVersion()) || '' | |
if (wxVersion) {let v = wxVersion.split('.') | |
if (Number(v[0]) >= 7) {if (Number(v[1]) >= 0) {if (Number(v[2]) >= 12) {setEnableLaunchWeapp(true) | |
} | |
} | |
} | |
} |
真的太恶心了,果决抽离成 hook。代码如下:
import {useState, useEffect} from 'react'; | |
import {isWechat, getWeixinVersion} from 'utils'; | |
const useEnableLaunchWeapp = () => {const [enableLaunchWeapp, setEnableLaunchWeapp] = useState(false); | |
useEffect(() => {const wxVersion = isWechat() && getWeixinVersion() || '' | |
if (wxVersion) {let v = wxVersion.split('.') | |
if (Number(v[0]) >= 7) {if (Number(v[1]) >= 0) {if (Number(v[2]) >= 12) {setEnableLaunchWeapp(true) | |
} | |
} | |
} | |
} | |
}, []) | |
return enableLaunchWeapp | |
} | |
export default useEnableLaunchWeapp; |
逻辑也很简略,在刚加载时判断它是否能够点击,能够点击,就设置 enableLaunchWeapp
为 true。应用办法也很简略
import React, {useState, useEffect} from 'react'; | |
import {Dispatch, History} from 'umi'; | |
import {OpenAppPopup} from 'components'; | |
+import {useEnableLaunchWeapp} from 'hooks'; | |
import {toDownloadApp} from 'utils'; | |
interface KVProps {history: History;} | |
const KV: React.FC<KVProps> = (props) => {const { history} = props; | |
const [isShow, setIsShow] = useState(false); | |
+const enableLaunchWeapp = useEnableLaunchWeapp(); | |
const onHandleClickToBuy = () => {setIsShow(true); | |
}; | |
const onHandleClickToSubmit = () => {+if (!enableLaunchWeapp) {+ toDownloadApp() | |
+} | |
} | |
return (<div className="KV" style={{ background: kvBgColor}}> | |
<div className="KV__content"> | |
<img src={img} alt="" /> | |
</div> | |
<OpenAppPopup | |
show={isShow} | |
onCancel={() => {setIsShow(false); | |
}} | |
onSubmit={onHandleClickToSubmit} | |
/> | |
</div> | |
); | |
}; | |
export default React.memo(KV); |
与 App 交互
需要点里说:要在所在页面跳转至 App 绝对页面,文档上写的很显著,能够传参数 extinfo="your-extinfo"
,轻易写了个让客户端同当时测试先
未唤醒 App
我手机是 IOS 的,是能够唤起的,然而安卓共事调试的时候说,后盾运行时,能够唤起 App,然而没有切换动作;如果杀掉过程,就无奈唤起。而这问题,大概率是 SDK 配置的问题,共事看了半天没解决,扔给他 Android 接入指南。我又看不懂 Android,只能看他了
如果测试胜利,能跳过去,那么就把本页链接当作 extinfo 传过来,他那边接管到 extinfo 后,做个映射表,跳转至本身的页面即可,所以 WxOpenLaunchApp 须要革新,多一个 extinfo 参数。。。
后记
因为咱们用的是 flutter,共事说,因为引入的第三方库不反对,所以跳不过来,所以这个性能要后置,等他搞定了我再做更新
错误处理
除了在 WxOpenLaunchApp 组件中退出监听 error,谬误就让它跳转至 App 外,还要做当微信或者零碎版本不反对微信标签时,须要监听并进行回退兼容,代码如下:
document.addEventListener('WeixinOpenTagsError', function (e: any) {console.error(e.detail.errMsg) // 无奈应用凋谢标签的谬误起因,需回退兼容。仅无奈应用开发标签,JS-SDK 其余性能不受影响 | |
toDownloadApp()}) |
总结
又复用就抽离成组件
必须要上生产环境,所以最好是有个预生产环境
参考资料
- 微信开发社区
- 应用微信 wx-open-launch-app 标签实现微信网页关上 App 记录
- 微信凋谢标签 wx-open-launch-app 款式设置技巧
- wx-open-launch-weapp 款式问题