Vue專案history模式下微信分享總結

justyeh發表於2019-03-28

每回遇到微信分享都是一個坑,目前的商城專案使用Vue開發,採用history的路由模式,配置微信分享又遇到了很多問題,最後終於解決了,現將解決的過程分享一下。

原文justyeh.top/post/39

技術要點

Vue,history

常見問題及說明

debug模式下報false

這個沒得說,就是呼叫wx.config方法的引數錯誤造成的,請確認以下事項:

  1. 是否成功繫結了域名(域名校驗檔案要能被訪問到)
  2. 使用最新的js-sdk檔案,因為微信會改部分api
  3. config方法的引數是否傳正確了(拼寫錯誤、大小寫...)
  4. 需要使用的方法是否寫在了jsApiList
  5. 獲取簽名的url需要decodeURIComponent
  6. 後臺的生成簽名的加密方法需要對照官方文件

debug返回ok,分享不成功

  1. 確保程式碼拼寫正確
  2. 分享連結域名或路徑必須與當前頁面對應的公眾號JS安全域名一致
  3. 介面呼叫需要放在wx.ready方法中

單頁專案(SPA)中的一些要點

所有需要使用JS-SDK的頁面必須先注入配置資訊,否則將無法呼叫(同一個url僅需呼叫一次,對於變化url的SPA的web app可在每次url變化時進行呼叫,目前Android微信客戶端不支援pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題會在Android6.2中修復)。

上面那段話摘自官方文件

開發者需要注意的事項:

  1. android和ios需要分開處理
  2. 需要在頁面url變化的時候重新呼叫wx.config方法,android獲取簽名的url就傳window.location.href
  3. Vue專案在切換頁面時,IOS中瀏覽器的url並不會改變,依舊是第一次進入頁面的地址,所以IOS獲取簽名的url需要傳第一次進入的頁面url

Code

router/index.js

......
import { wechatAuth } from "@/common/wechatConfig.js";
......

const router = new Router({
    mode: "history",
    base: process.env.BASE_URL,
    routes: [
        {
            path: "/",
            name: "home",
            meta: {
                title: "首頁",
                showTabbar: true,
                allowShare: true
            },
        },
        {
            path: "/cart",
            name: "cart",
            meta: {
                title: "購物車",
                showTabbar: true
            },
            component: () => import("./views/cart/index.vue")
        }
        ......
    ]
});


router.afterEach((to, from) => {
    let authUrl = `${window.location.origin}${to.fullPath}`;
    let allowShare = !!to.meta.allowShare;

    if (!!window.__wxjs_is_wkwebview) {// IOS
        if (window.entryUrl == "" || window.entryUrl == undefined) {
            window.entryUrl = authUrl; // 將後面的引數去除
        }
        wechatAuth(authUrl, "ios", allowShare);
    } else {
        // 安卓
        setTimeout(function () {
            wechatAuth(authUrl, "android", allowShare);
        }, 500);
    }
});
複製程式碼

程式碼要點:

  1. meta中的allowShare用於判斷頁面是否可分享
  2. window.__wxjs_is_wkwebview可用來判斷是否是微信IOS瀏覽器
  3. entryUrl是專案第一次進入的頁面的地址,將其快取在window物件上
  4. 為什麼安卓的時候要增加一個延時器,因為安卓會存在一些情況,就是即便籤名成功,但是還是會喚不起功能,這個貌似是一個比較穩妥的解決辦法

wechatConfig.js

import http from "../api/http";
import store from "../store/store";

export const wechatAuth = async (authUrl, device, allowShare) => {
    let shareConfig = {
        title: "xx一站式服務平臺",
        desc: "xxxx",
        link: allowShare ? authUrl : window.location.origin,
        imgUrl: window.location.origin + "/share.png"
    };

    let authRes = await http.get("/pfront/wxauth/jsconfig", {
        params: {
            url: decodeURIComponent(device == "ios" ? window.entryUrl : authUrl)
        }
    });

    if (authRes && authRes.code == 101) {
        wx.config({
            //debug: true,
            appId: authRes.data.appId,
            timestamp: authRes.data.timestamp,
            nonceStr: authRes.data.nonceStr,
            signature: authRes.data.signature,
            jsApiList: ["updateAppMessageShareData", "updateTimelineShareData", "onMenuShareAppMessage", "onMenuShareTimeline"]
        });

        wx.ready(() => {
            wx.updateAppMessageShareData({
                title: shareConfig.title,
                desc: shareConfig.desc,
                link: shareConfig.link,
                imgUrl: shareConfig.imgUrl,
                success: function () {//設定成功
                    //shareSuccessCallback();
                }
            });
            wx.updateTimelineShareData({
                title: shareConfig.title,
                link: shareConfig.link,
                imgUrl: shareConfig.imgUrl,
                success: function () {//設定成功
                    //shareSuccessCallback();
                }
            });
            wx.onMenuShareTimeline({
                title: shareConfig.title,
                link: shareConfig.link,
                imgUrl: shareConfig.imgUrl,
                success: function () {
                    shareSuccessCallback();
                }
            });
            wx.onMenuShareAppMessage({
                title: shareConfig.title,
                desc: shareConfig.desc,
                link: shareConfig.link,
                imgUrl: shareConfig.imgUrl,
                success: function () {
                    shareSuccessCallback();
                }
            });
        });
    }
};

function shareSuccessCallback() {
    if (!store.state.user.uid) {
        return false;
    }
    store.state.cs.stream({
        eid: "share",
        tpc: "all",
        data: {
            uid: store.state.user.uid,
            truename: store.state.user.truename || ""
        }
    });
    http.get("/pfront/member/share_score", {
        params: {
            uid: store.state.user.uid
        }
    });
}

複製程式碼

總結

原先計劃不能分享的頁面就使用hideMenuItems方法隱藏掉相關按鈕,在ios下試了一下,有些bug:顯示按鈕的頁面切換的影藏按鈕的頁面,分享按鈕有時依然存在,重新整理就沒問題,估計又是一個深坑,沒精力在折騰了,就改為隱私頁面分享到首頁,公共頁面分享原地址,如果有什麼好的解決辦法,請聯絡我!

一開始我有參考sf上的一篇部落格segmentfault.com/a/119000001…,按照上面的程式碼,android手機都能成功,但是IOS有一個奇怪的問題,就是分享間歇性的失效,同一個頁面,剛剛調起分享成功,再試一次就失敗(沒有圖示、title,只能跳轉到首頁),經過“不斷”努力的嘗試,應該是解決了問題,說一下過程:

  1. 一開始以為是非同步喚起沒成功的問題,就和android一樣給IOS呼叫wechatAuth方法也加了個定時器,測了一遍沒效果,放棄

  2. 起始js-sdk是通過npm安裝的,版本上帶了個test,有點不放心,改為直接使用script標籤引用官方的版本

  3. 重新讀了一遍文件,發現onMenuShareTimeline等方法即將廢棄,就把jsApiList改為jsApiList:['updateAppMessageShareData','updateTimelineShareData'],改後就變成了IOS可以成功,android分享失敗

  4. 百度updateAppMessageShareData安卓失敗原因,參考這個連結www.jianshu.com/p/1b6e04c29…,把老的api也加到jsApiList中,仔細、反覆試了試兩種裝置都ok,好像是成功了,說"好像"是因為心裡沒底啊,各種“魔法”程式碼!

最後,在這裡希望騰訊官方能不能走點心,更新文件及時點,demo能不能提供完整點....

參考連結

segmentfault.com/a/119000001… www.jianshu.com/p/1b6e04c29… segmentfault.com/a/119000001… github.com/vuejs/vue-r…

相關文章