Vue-CLI 的 H5 在手机QQ分享配置的天坑!

官方提供的资料:

腾讯移动Web开发平台 : 15年最后一次更新, 可想而知放在如今QQ中调用的准确性!这里面提供了一些QQWebView 相关配置的接口, 也只是一些接口。官网中提供的“通用API”和“手机QQ”页面中使用的全局对象mqq,引入方式为:<script src="//open.mobile.qq.com/sdk/qqapi.js"></script>,其中就有不少可以配置分享的接口:

window.mqq.invoke("data","setShareInfo", {
    share_url: window.OPEN_DATA && window.OPEN_DATA.shareurl,
    title: 'H5应用',
    desc: 'H5开放平台',
    image_url: 'http://i.gtimg.cn/open/app_icon/05/58/35/77/1105583577_100_m.png'
});
 // 另外使用meta同样可以达到该接口的作用
 <meta itemprop="name" content="这是分享的标题"/>
 <meta itemprop="image" content="http://imgcache.qq.com/qqshow/ac/v4/global/logo.png" />
 <meta name="description" itemprop="description" content="这是要分享的内容" />
// H5应用设置方法 (我觉得该方法是需要配置腾讯白名单才能正常使用的,否则设置无效,请往下阅读)
mqq.ui.setOnShareHandler(function(type){
    mqq.ui.shareMessage({
        title: '自定义的分享标题',
        desc: '自定义的分享描述',
        share_type: type,
        share_url: window.OPEN_DATA.shareurl,
        image_url: 'http://i.gtimg.cn/open/app_icon/05/58/35/77/1105583577_100_m.png',
        back: true
    },function(result){
        //result
    });
});

其中对外分享组件接口文档 中说引入<script src="//qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js"></script> 使用全局 setShareInfo 方法定制手机QQ APP内的分享内容:

setShareInfo({
    title:          '父爱,在你看不到的地方', // 分享标题
    summary:        '父爱如山,感觉不到只因身在此山中', // 分享内容
    pic:            'http://qzonestyle.gtimg.cn/aoi/sola/20150617094556_OvfOpoRKRB.png', // 分享图片
    url:            'http://qzs.qzone.qq.com/qzone/qzact/act/2015/father-day-m/index.html', // 分享链接
});

手机QQ打开 QQAPI官方测试Demo,可以大概看看都提供哪些方法,是否有效,也可以看看源码都如何调用,有助理解。

遇到的问题:

手机QQ 环境下,网页的分享可以不用去使用QQAPI去配置分享样式, 按上面所说直接设置<meta>标签就行了, 但是对于 Vue 框架的页面来说,就可能存在问题,确切的说是 Vue 框架中使用 # 控制路由,在QQ分享出来就可能会出现奇怪的问题( 如果使用 history 路由模式应该不会有问题),下面针对使用 # 作为路由方式的H5在QQ中分享中我所遇到的问题及解决方案进行记录。

Q1 : iPhone QQ 分享出去的页面在 iPhoneQQ 无法打开(服务器报错)或页面 404 (Android打开没有问题)

举个🌰

Hash 模式下的URL是这样的 http://localhost/index.html#/home?a=1 ,当该连接在QQ里打开并使用QQ提供的分享功能分享出来的时候,分享出来的链接可能就会变成 http://localhost/index.html&appinstall=0#/home?a=1,QQ会在URL中自动拼接上&appinstall=0 而且在 # 前面,这就会直接导致服务器解析URL错误,页面无法正常打开。

当然,这种问题并不是100%出现的,根据我目前的尝试,满足以下条件会出现该问题:
URL长度大于140 且 iPhoneQQ 环境分享出去 并 在 iPhoneQQ 打开分享页面

我的解决方案:

我在项目入口文件的 index.html<head>中第一行加上替换分享默认参数的JS

<head>
<script type="text/javascript">
    // 去除QQ微信分享时默认插入的参数
    if (/from=[^&$?]{1,}(&|$)/.test(location.search) || /isappinstalled=[^&$?]{1,}(&|$)/.test(location.search) || /appinstall=[^&$?]{1,}(&|$)/.test(location.search)) {
      var newSearch = location.search.replace(/from=[^&$?]{1,}(&|$)/, '').replace(/isappinstalled=[^&$?]{1,}(&|$)/, '').replace(/appinstall=[^&$?]{1,}(&|$)/, '').replace(/&$|\?$/, '')
      var newUrl = location.origin + location.pathname + newSearch + location.hash
      document.location.replace(newUrl)
    }
  </script>
  ...
</head>

当然, 如果添加的参数导致服务器无法解析, 也根本就不会进入到这里。所以我想到了下面的方法去避免出现服务器无法解析的URL

项目的main.js中在配置 router 的时候监听在 iPhoneQQ 环境下,当某页面的URL过长时,在index.html后添加?1=1 这样可以避免被QQ添加&appinstall=0直接导致URL解析错误。最终分享后打开变成index.html?1=1&appinstall=0,至少可以正常访问。

router.afterEach((to, from) => {
  // 加个延迟, 不然 window.location.href 不会变
  setTimeout(function () {
    if (mqq && mqq.platform == 'iPhoneQQ' && window.location.href.length > 140) {
      // iPhoneQQ 上URL长度大于140会, QQ分享默认会插入参数导致url格式错误从而服务端报错, 需改成 xxx/index.html?1-1#/?param=xxx
      console.log(location.href.replace('index.html#', 'index.html?1=1#'))
      document.location.replace(location.href.replace('index.html#', 'index.html?1=1#'))
    }
  }, 100);
})

上述方法可解决问题。

Q2:配置分享样式失效。

一般情况可以通过设置<meta>标签即可, 也可以通过 JS 去自行修改内容;

 <meta itemprop="name" content="这是分享的标题"/>
 <meta name="description" itemprop="description" content="这是要分享的内容" />
 <meta itemprop="image" content="http://imgcache.qq.com/qqshow/ac/v4/global/logo.png" />

// 手动修改
$("meta[itemprop='name']").attr('content', title)
$("meta[itemprop='description']").attr('content', desc)

这种情况分享出去样式为:Android 标题和子标题是 meta 的 name 和 description, iPhone 标题是 document.title ,子标题是 meta 的 description

也可以使用 QQAPI:

  // 引入 <script src="//qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js"></script>
setShareInfo({
  title: params.title, // 分享标题
  summary: params.desc, // 分享内容
  pic: 'http://imgcache.qq.com/qqshow/ac/v4/global/logo.png', // 分享图片
  url: window.location.href, // 分享链接
})

// 或者 引入 <script src="//open.mobile.qq.com/sdk/qqapi.js"></script>
window.mqq.invoke('data', 'setShareInfo', {
  share_url: window.location.href,
  title: params.title,
  desc: params.desc,
  image_url: 'http://imgcache.qq.com/qqshow/ac/v4/global/logo.png'
})

使用QQAPI一定要注意的地方

QQAPI 提供的所有方法包括上面的分享配置方法),我在实验后猜测只在域名为 .com 或 .cn 或者在 “腾讯白名单” 下才有效果,否则怎么设置都没有效果。我司域名 测试环境为 .cn 生产环境为 .cc,测试环境没问题,生产环境不行。所以在使用前务必请知晓这块,如果真遇到设置无效的情况,估计就是这样原因。坑的我一口老血....(至于怎么加入白名单,没有入口,无从知晓,怕是只有内部跟腾讯合作吧~)

在QQAPI分享配置无效的情况下,配置分享样式可以使用上述的 document.title<meta> 标签去配置了,但是目前发现,AndroidQQ下如果index.html中没有<title></title>标签,是无法配置分享样式的,请务必加上。此时 AndroidQQ 分享的标题我觉得应该是页面加载完成后的 document.title,所以之后再设置 document.title 就无效了。

在QQAPI分享配置有效的情况下,上述两个分享配置方法功能是一样的,效果为:Android分享的样式完全有参数控制,但是iPhone上分享出来的样式为 标题是 document.title ,子标题是 meta 的 description

Q3:QQAPI配置分享无效时,AndroidQQ上,分享通过路由跳转的页面,打开看到的却是首页。

在QQAPI配置分享无效的情况下,我发现仅在AndroidQQ上会出现该问题,明明分享的是其他页面,可打开分享消息展示的却是第一个页面。也就是 Vue的 # 路由机制无法触发QQ去更新分享出去的URL。即使不使用 $router 调整页面,使用 location.href = xxxx 也是不行的。我猜测,只改变 # 后面的路由和参数无法触发 QQ 更新 分享出去的 URL。
我想到使用QQAPI的

mqq.invoke('ui', 'openUrl', {
  url: url,
  target: 1,
  style: 0
})

方法重新打开一个 WebView 展示其他页面,可最终发现在测试环境下可以解决,但生产环境不行,原因就是 .cc 域名下 QQAPI 的方法无效。如果域名后缀是.com 或 .cn可以尝试用此方法解决子页面分享问题。

最终 我发现在index.html后面添加参数(index.html?1=1/#hello?a=1)是可以触发 QQ 更新分享出去的URL的。简直了~

我的解决方案:
if (mqq && mqq.platform.indexOf('AndroidQQ') != -1) {
  // AndroidQQ 在域名为.cc下分享无法配置,QQ分享配置监听不了Vue路由变化,即 #后面的变化并不会让 QQWebview 改变分享配置,所以Android这样处理 index.html?1=1 可刷新分享配置
  let url = window.location.href.split('index.html')[0] + 'index.html?1=1#/hello?a=1'
  window.location.href = url
} else {
  this.$router.push({
    path: '/hello',
    query: {
      a: 1
    }
  })
}

自此,目前关于 Vue 框架写的H5页面在QQ分享的问题基本解决。确实挺坑的,尤其是域名问题。以上是我个人在实践中的整理。如果有什么不对的地方或者有更好的解决方法也请指出和交流。

请注意:iPhoneQQ分享有次数限制,大约100次左右,超出后对方看不到消息,但自己能看到,大约被“封”两天 😂

参考资料

掘金 Crazy_Urus 移动端H5多平台分享实践
Github AOTU Labs 手Q分享接口 - 基础篇
Github AOTU Labs 手Q分享接口 - 填坑篇
CSDN 武东10号 iOS下,H5地址从webview分享到QQ,微信打不开自动拼接appinstall=0地址,问题解决方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270