> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# history 模式分享

## 前言

最近做的**Vue SPA**项目涉及到微信自定义分享，最初只是在指定页面下实现微信的二次分享功能。但是因为移动端使用的是**vue-router**的**history 模式**，所以在 iOS 端微信和 Android 端微信分享出来的截然不同，大多数是**iOS 端微信**会分享失败。上网查询了一些文档说是 iOS 端微信**不支持 pushState 的 H5 新特性**。还有就是 iOS 端微信记录的 URL 是首次访问网页时的网址，所以在使用**window\.location.href**获取当前网址来换取微信的签名校验信息时候就会导致签名校验失败，致使最终微信分享失败。

## 解决方案

**iOS 端微信处理方法**：保存首次进入页面时候的路径，在需要调用微信分享的页面内利用**首次进入页面时候的路径 URL**来换取**iOS**端微信分享的签名。

**Android 端微信处理方法**：Android 端微信每次切换路由时候都会刷新页面，故在需要使用微信分享的页面直接获取**当前页面所在路径的 URL**即使用**window\.location.href**来换取微信分享的签名即可。

## 判断设备

Android 设备环境：

```javascript title="设备环境"
let ua = navigator.userAgent;
// 方法一
let isAndroid = ua.indexOf("Android") > -1 || ua.indexOf("Linux") > -1;
// 方法二
let isAndroid = ua.indexOf("Android") > -1 || ua.indexOf("Adr") > -1;
// 方法三
let isAndroid = /(Android)/i.test(navigator.userAgent);
```

iOS 设备环境：

```javascript title="设备环境"
// 方法一
let isiOS = !!window.__wxjs_is_wkwebview;
// 方法二
let isiOS = /iPhone|mac|iPod|iPad/i.test(navigator.userAgent);
// 方法三
let u = navigator.userAgent;
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
```

## 主要代码

- **封装 wxShare.js**

```javascript title="代码示例"
import axios from "axios";
import store from "../store";
/* 微信自定义分享 */
/**
 * url：获取微信分享签名的url地址
 * device：iOS&Android设备的区分
 * isShare：当前所在路径是否需要分享
 *  */
const WeChatShare = (url, device, isShare) => {
    if (!isShare) {
        return;
    }
    let xxx = store.state.xxx;
    let shareLink = window.location.origin + "?xxx=" + xxx;
    if (store.state.xxxx == "") {
        return;
    }
    let { title, imgUrl, link, desc } = store.state.xxxx;
    if (device == "iOS") {
        // 获取iOS微信首次存储的URL
        url = sessionStorage.getItem("iOS-URL");
    } else {
        url = window.location.href;
    }
    if (url.includes("#")) {
        url = url.split("#")[0];
    }
    // 获取时间戳
    axios
        .get("wx/api", { params: { url: decodeURIComponent(url) } })
        .then((res) => {
            if (res.data.code == 1) {
                let { timestamp, noncestr, signature } = res.data.result_data;
                // 校验
                wx.config({
                    debug: false,
                    appId: "appId",
                    timestamp: timestamp,
                    nonceStr: noncestr,
                    signature: signature,
                    jsApiList: [
                        "checkJsApi",
                        "updateAppMessageShareData",
                        "updateTimelineShareData",
                    ],
                });
                // 检测
                wx.ready(() => {
                    wx.checkJsApi({
                        jsApiList: [
                            "updateAppMessageShareData",
                            "updateTimelineShareData",
                        ],
                        success: function (res) {},
                    });
                    // 自定义“分享给朋友”及“分享到QQ”（1.4.0）
                    wx.updateAppMessageShareData({
                        title: title,
                        desc: desc,
                        link: link,
                        imgUrl: imgUrl,
                        success: () => {},
                    });
                    // 自定义“分享到朋友圈”及“分享到QQ空间”（1.4.0）
                    wx.updateTimelineShareData({
                        title: title,
                        link: link,
                        imgUrl: imgUrl,
                        success: () => {},
                    });
                });
            }
        })
        .catch((err) => {
            console.log("JSSDK share error：", err);
        });
};
```

- **分享链接处理**

```javascript title="代码示例"
/* 处理分享链接 */
const shareLink = (location) => {
    let origin = location.origin,
        search = location.search;
    if (search.includes("&")) {
        search = search.split("&")[0];
    }
    let link = origin + search;
    return link;
};
```

- **router.js 多路径自定义分享设置**

```javascript title="代码示例"
// 设备判断
let ua = navigator.userAgent;
// Android
let isAndroid = ua.indexOf("Android") > -1 || ua.indexOf("Linux") > -1;
// iOS
let isIos = !!window.__wxjs_is_wkwebview;
// 微信二次分享
router.afterEach((to, from) => {
    let authUrl = `${window.location.origin}${to.fullPath}`;
    let allowShare = !!to.meta.allowShare;
    // IOS
    if (isIos) {
        authUrl = sessionStorage.getItem("iOS-URL");
        WeChatShare(authUrl, "iOS", allowShare);
    }
    // Android
    if (isAndroid) {
        setTimeout(() => {
            WeChatShare(authUrl, "android", true);
        }, 400);
    }
});
```

:::tip 总结

在 vue 项目中只是分享某一个路径下的页面，即可在当前页面路径下引入写好的微信分享文件方法，在需要分享的页面进行调用即可。

在**Vue** **SPA** 项目 **history 模式** 中，指定页面需要实现动态分享，其余路径页面实现固定分享，既可以在 router.js 的 **router.afterEach((to,from)=>\{})** 全局生命周期钩子函数中调用微信分享方法即可实现指定路径页面动态分享，其余路径页面固定分享的需求。

hash 模式，直接按照 Android 端微信的调用方式即可。如有问题，可依据此思路作为参考，并结合实际需求进行相应的调整。
:::
