2

Prerequisites

The function positioning of the author's project on WeChat is the basic function transaction and service, notifying users of transaction reminders, transaction flow, etc., and the APP is the main transaction function. Previously, there were drainage buttons on multiple pages to jump to the App, and the function points were relatively crude, directly location.href = 应用宝链接 . Now there is demand for the product, and it is said that the label provided by WeChat should be used to evoke the App

Requirements:

All the parts that jump to the app download page, change to

需求点

Demo first

In case of indecision, the official website document . After viewing it, it is very similar to the WeChat JS-SDK function. I will skip it without nonsense here. According to the official website demo, write the example into the business code

 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);

The test is successful, the demo can run through

Component Pilot

Now I'm doing business, using this component (Download) as a pilot to expand, I want to click on the card at the top of the page (used in multiple places, extract it into a Download component), let it evoke the App, but I have to judge its version, if the version is too low, Let it jump to the app treasure

 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);

The effect is as follows:

点击范围

Idea logic reference: wx-open-launch-weapp style problem , I also color it for follow-up observation

Test synchronization, you can click on the card to jump, OK, next step, add code like this to all the places where you need to click to jump to the page

 <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>

Package component WxOpenLaunchApp

If so, you can package it into a component, give it a name: WxOpenLaunchApp

Wrap the content that evokes the App into a component, thunder children and style two props, the code is as follows:

 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);

Then the Download component can be much cleaner

 ...
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>
        ...
    )
}
...

Business ComponentOpenAppPopup

Back to the demand point, a pop-up box will pop up every clicked place, click 打开 App , and then call up the App, in this case, the pop-up box + WxOpenLaunchApp can be combined into a component, which is released for the page to call, the name It is called OpenAppPopup , the code is as follows:

 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);

The schematic diagram is as follows:

OpenAppPopup

Then you can use this logic on all pages with jump apps

Encapsulation HOOK

When you click a button similar to 下载App on each page, it will pop up OpenAppPopup , click 打开App , you need to judge whether your WeChat version reaches 7.0.12, if each The page should add this

 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)
      }
    }
  }
}

It's really disgusting, so I decided to pull it off into a hook. code show as below:

 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;

The logic is also very simple. To judge whether it can be clicked and clickable when it is just loaded, set enableLaunchWeapp to true. It is also very simple to use

 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);

Interact with the App

The demand point says: To jump to the relative page of the App on the page where you are located, it is clearly written in the document, you can pass the parameters extinfo="your-extinfo" , just write a random one for the client colleagues to test first

App not awakened

My mobile phone is IOS and can be evoked, but when my Android colleague was debugging, they said that when running in the background, the app can be evoked, but there is no switching action; if the process is killed, it cannot be evoked. And this problem is most likely a problem with the SDK configuration. My colleague didn't solve it after reading it for a long time, and threw him the Android access guide . I can't read Android anymore, I can only watch him

If the test is successful and you can jump over, then pass the link of this page as extinfo. After receiving the extinfo, he can make a mapping table and jump to its own page, so WxOpenLaunchApp needs to be modified, and one more extinfo parameter. . .

postscript

Because we are using flutter, my colleague said that because the imported third-party library does not support it, it cannot be skipped, so this function needs to be set later, and I will update it when he is done.

error handling

In addition to adding monitoring error to the WxOpenLaunchApp component, and making it jump to the App if the error occurs, it is also necessary to monitor and perform fallback compatibility when WeChat or the system version does not support WeChat tags. The code is as follows:

 document.addEventListener('WeixinOpenTagsError', function (e: any) {
  console.error(e.detail.errMsg) // 无法使用开放标签的错误原因,需回退兼容。仅无法使用开发标签,JS-SDK其他功能不受影响
  toDownloadApp()
})

Summarize

After reuse, it can be extracted into components

The production environment must be used, so it is best to have a pre-production environment

References


山头人汉波
394 声望555 粉丝