微信分享,首先參考微信JS-SDK開發文檔。
step1:在啟動文件index.html中引入微信js文件;
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
step2:微信config接口注入權限驗證配置。新建wechat.service.ts文件進行相關配置。文件建好之后在app.module.ts文件中引入WechatService,程序中的所有頁面都能使用該服務,不需要逐個頁面引入服務。
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { URLService } from './urls';
import { WechatShareModel } from '../model-res/wechat-share-model';
import { Observable, Subscriber } from 'rxjs';
import { CommonService } from './common.service';
declare var wx: any;
@Injectable()
export class WechatService {
constructor(
private http: Http,
private us: URLService,
private cs: CommonService,
) { }
jfOnMenuShareAppMessage(shareData?: WechatShareModel) {
if (!shareData) {
shareData = new WechatShareModel();
}
let shareD = {
title: shareData.title, // 分享標題
desc: shareData.desc, // 分享描述
link: shareData.link, // 分享鏈接
imgUrl: shareData.imgUrl, // 分享圖標
type: shareData.type, // 分享類型,music、video或link,不填默認為link
dataUrl: shareData.dataUrl, // 如果type是music或video,則要提供數據鏈接,默認為空
success: function () {
// 用戶確認分享后執行的回調函數
},
cancel: function () {
// 用戶取消分享后執行的回調函數
}
}
wx.onMenuShareAppMessage(shareD);
}
getWechatConfigFun(): any {
//便於PC端調試
return new Observable(x => this.getWechatConfig(x));
//正式上線
// if (this.cs.IsWeChatFun()) {//判斷是否是微信瀏覽器
// return new Observable(x => this.getWechatConfig(x))
// } else {
// return new Observable(x => x.next('非微信瀏覽器!'))
// }
}
private getWechatConfig(x: Subscriber<any>) {
let wechatUrl = location.href.split('#')[0];
//使用encodeURIComponent()的原因請參考 附錄4-常見錯誤及解決方法;
let url = this.us.getUrl('wechatConfig', { url: encodeURIComponent(wechatUrl) });
this.http.get(url).subscribe(res => {
let configData = res.json().data;//處於安全考慮timestamp、nonceStr、signature等信息在服務器端處理。
delete configData['url'];
configData['appId'] = 'wx8888888888888888';
configData['debug'] = false;//開啟調試模式,調用的所有api的返回值會在客戶端alert出來.
configData['jsApiList'] = ['onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareTimeline', 'onMenuShareWeibo', 'onMenuShareQZone'];
wx.config(configData)//config接口注入權限驗證
wx.ready(() => {
x.next(200);
})
wx.error((res) => {
x.next('微信配置錯誤');//配置失敗,返回錯誤信息都可以查看微信文附錄4-常見錯誤及解決方法
}) }, () => { x.next('微信權限驗證配置API連接錯誤!'); }) } }
setp3:新建main.ts,並在需要分享的頁面繼承;
import { ViewChild } from '@angular/core';
import { Content, Footer } from 'ionic-angular';
import { WechatService } from './wechat.service';
import { WechatShareModel } from '../model-res/wechat-share-model';
export class MainPage {
@ViewChild(Content) content: Content;
@ViewChild(Footer) footer: Footer;
shareDatas: WechatShareModel = null;//存儲當前頁面需要分享的相關信息
timer;
downTime = 0;//如果當前頁面30秒后認為設置分享數據,則使用默認分享數據
constructor(public wechat: WechatService) { }//wechat需要聲明public才能繼承,繼承該文件的頁面也需要聲明public的wechat
ionViewDidEnter() {
//二級頁面繼承MainPage
//二級頁面刷新處理start
let tabbarEles = document.querySelectorAll(".tabbar");
Object.keys(tabbarEles).map((key) => {
tabbarEles[key].style.zIndex = '0';//二級頁面不顯示tabs,因為ionic2模式下刷新當前頁面是會出現tabs底部導航
});
this.content._scrollContent.nativeElement.style.marginBottom = '0px';
if (this.footer) {
//如果二級頁面存在底部自定義按鈕
//需要調整文本content的margin-bottom
//需要調整footer距離底部的位置
this.footer._elementRef.nativeElement.style.bottom = '0px';
this.content._scrollContent.nativeElement.style.marginBottom = '50px';
}
//二級頁面刷新處理end
//ionViewDidEnter()中進行微信API接口的配置;
//①每次進入頁面都會執行,保證每一次的分享數據的實時更新。避免分享的數據是之前訪問的頁面數據
this.ngAfterShare();
}
ionViewWillLeave() {
//離開頁面之前對tabs的處理,要不然返回之后沒有底部導航
let tabbarEles = document.querySelectorAll(".tabbar");
Object.keys(tabbarEles).map((key) => {
tabbarEles[key].style.zIndex = '10';//離開頁面之前撤銷刷新頁面之后的修改。
});
if (this.timer) {
clearInterval(this.timer)
}
}
ngAfterShare(pageISNoReload?: boolean) {
let $this = this;
if (pageISNoReload) {
//部分頁面沒有跳轉,直接在當前頁面獲取新的數據時候也需要設置新的分享數據。
//使用場景
//例如:商品搜索頁面,頁面進行在次搜索,或者點擊分類篩選等,避免分享的數據是最初的數據,需要實時更新分享數據
//搜索頁面點擊搜索,更新分享鏈接
$this.wechat.getWechatConfigFun().subscribe(res2 => {
//避免沒有獲取到數據的使用默認設置的分享數據
if (res2 == 200) {
$this.wechat.jfOnMenuShareAppMessage(this.shareDatas);
}
})
} else {
//使用setInterval()反復進行微信配置,主要是頁面獲取數據存在異步。
this.timer = setInterval(() => {
$this.downTime += 1;
if ($this.downTime >= 30) {
$this.shareDatas = new WechatShareModel();//設置默認分享的數據
}
console.log('titmer');
if ($this.shareDatas) {
//設置完成當前頁面的分享數據
if ($this.timer) {
clearInterval($this.timer);
}
//進行微信config的配置
$this.wechat.getWechatConfigFun().subscribe(res2 => {
//避免沒有獲取到數據的使用默認設置的分享數據
if (res2 == 200) {
let link = '';
if (location.href.indexOf('params') > -1) {
let params = location.href.split('#')[1];
//避免從分享出去的入口進入再分享。
//需要重新設置分享的連接
//
link = location.href.split('?params')[0] + '?params=' + params;
} else {
//例如當前頁面hash格式:http://m.hxyxt.com/www/#/tabs/t0/%E7%A7%AF%E5%88%86%E5%95%86%E5%9F%8E/jfProduct/100017632
//微信配置中會自動過濾掉#號后邊的地址,所以需要需要將#好后邊的url作為參數設置成當前頁面的分享地址;
//
link = location.href.split('#')[0] + '?params=' + location.href.split('#')[1];
//重新拼接的地址:http://m.hxyxt.com/www/?params=/tabs/t0/%E7%A7%AF%E5%88%86%E5%95%86%E5%9F%8E/jfProduct/100017632
}
if (!$this.shareDatas.link) {
$this.shareDatas.link = link;
}
$this.wechat.jfOnMenuShareAppMessage($this.shareDatas);
}
})
}
}, 1000)
}
}
}
以下是默認的分享模板
export class WechatShareModel { title: string = '' // 分享標題 desc: string = '' // 分享描述 link: string = '' // 分享鏈接 imgUrl: string = ‘’; //分享圖片 type: string = '' // 分享類型 music、video或link,不填默認為link dataUrl: string = '' // 如果type是music或video,則要提供數據鏈接,默認為空 }
step4:在需要設置分享的頁面繼承MainPage。以商品詳情頁面為例。
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { JfProductService } from './jf-product.service';
import { ProductLunboslideshowModel } from '../../model-res/jf-home-model';
import { CommonService } from '../../common/common.service';
import { MsgBarService } from '../../common/msg-bar';
import { MainPage } from '../../common/main';
import { WechatService } from '../../common/wechat.service';
import { UserService } from '../user/user.service';
@IonicPage({
name: 'jfProduct',
segment: 'jfProduct/:p0',
defaultHistory: ['jfHome']
})
@Component({
selector: 'page-jf-product',
templateUrl: 'jf-product.html',
})
export class JfProductPage extends MainPage {//繼承MainPage
lunboHeight;//輪播高度與屏幕寬度一致;
buyNum: number = 1;//記錄兌換的數量
infos;
pID: any;
slidesImgs: ProductLunboslideshowModel[] = [];
myIntergral: number = this.cs.getMyIntergral();
constructor(
private cs: CommonService,
private service: JfProductService,
public navCtrl: NavController,
public navParams: NavParams,
private ms: MsgBarService,
public wechat: WechatService,//
private us: UserService) {
super(wechat);//繼承需要寫入該方法。 this.lunboHeight = window.innerWidth;
this.pID = navParams.data.p0;
}
getProduct(e?) {
let loading = this.ms.loading('正在獲取商品數據……');
loading.present();
this.service.getIntegralProductDetail({ productCode: this.pID }).subscribe(res => {
//獲取商品詳情結束
loading.dismiss();
this.infos = res;
this.slidesImgs = new Array();
res.images.forEach((v, i) => {
if (v.imageType == 'GALLERY' && v.format == 'superZoom') {
let img: ProductLunboslideshowModel = {
code: '',
url: v.url,
type: ''
}
this.slidesImgs.push(img);
}
});
if (e) { e.complete(); }
//設置當前頁面的分享數據 start this.shareDatas = { title: '小伙伴,快來看看吧,【' + res.name + '】', desc: '只要【' + res.integral + '積分+' + res.vipPrice + '元】即可兌換!', link: '',//鏈接地址在MainPage的分享配置中統一設置 imgUrl: res.images[0].url, type: '', dataUrl: '', }
//設置當前頁面的分享數據 end
}, () => { loading.dismiss(); if (e) { e.complete(); } }) } }
step5:在微信中查看商品詳情並分享給微信朋友。

step5:分享出去的效果

以上,微信分享到“微信朋友”完成。
接下來是,點擊分享出去的連接,如何正確跳轉到指定的頁面。
//分享出去的連接
//http://m.hxyxt.com/www/?params=/tabs/t0/%E7%A7%AF%E5%88%86%E5%95%86%E5%9F%8E/jfProduct/100017234
//點擊分享出去的連接,都是默認跳轉到程序的默認啟動頁面,如商城首頁。所以需要在該頁面解析。
方法1:在頁面初始化時調用以下的方法(建議先往下看)
isShareView() { if (this.ls.retrieve('SHAREURLLOADED') && this.isLogin) { let params=this.ls.retrieve('SHAREURLLOADED'); this.ls.clear('SHAREURLLOADED'); window.location.href=location.href.split('#')[0]+params; } if (location.href.indexOf('params') > -1) { //存在該參數說明是分享出去的連接 let $this = this; setTimeout(() => { //需要進行一定的延時 let url = location.href; url = url.replace('?params=', '#'); url = url.split('#')[0]; console.log(location); let params = location.search;//獲取頁面參數部分 params = params.replace('?params=', '#');//解析成ionic路徑格式 console.log(params); //在LocalStorageService中存入該參數 this.ls.store('SHAREURLLOADED', params); window.location.replace(url);//重構當前頁面url,為了跳轉之后能回到首頁 }, 500) } }
弊端:直接改變頁面路徑會導致APP重啟,會看到兩次啟動頁面。用戶體驗不是很好。
優點:分享商品的link配置比較方便,不要再處理。
方法2:在頁面初始化時調用以下的方法
isShareView() { if (this.ss.retrieve('SHAREURLLOADED')) { return; } if (location.href.indexOf('params') > -1) { //分享出去的連接 let $this = this; setTimeout(() => { //需要進行一定的延時 let params = location.search; params = params.substring(params.lastIndexOf('params')) params = params.replace('params=/', ''); let para = params.split('/'); let gotoUrl = para[3]; let gotoParamsArr = new Array(); para.forEach((v, i) => { if (i > 3) { gotoParamsArr.push(v) } }); let gotoParamsObj = {}; gotoParamsArr.forEach((v, i) => { let item = 'p' + i; gotoParamsObj[item] = v; }); if ($this.isLogin) { //如果存在LocalStorageService的話,再次進入也不會跳轉到分享出去的頁面,所以存在session
$this.ss.store('SHAREURLLOADED', true);//標識用戶是否已經跳轉過分享出去的頁面。//避免頁面刷新重復看到應用啟動的效果。
$this.navCtrl.push(gotoUrl, gotoParamsObj);//解析成為頁面跳轉需要的數據格式。
}
}, 500) }
}
弊端:需要在分享配置link的時候進行url中的參數處理,否則分享出去的連接會存在多個params;
優點:①進入頁面之后根據分享得到的連接進行解析,轉成ionic跳轉頁面需要的格式。
②不更改頁面路徑,不會出現重新加載的啟動畫面。
③頁面實現跳轉比較平穩,用戶體驗效果更好。
20170920:補充頁面解析參數的方式
isShareView() { let paramsString = location.search; let searchParams = new URLSearchParams(paramsString); if (this.ss.retrieve('SHAREURLLOADED')) { return; } if (searchParams.has("params") === true) {
//分享出去的連接 let $this = this; setTimeout(() => { //需要進行一定的延時 let params = searchParams.get("params").split('/') let navPush = params[3];//要跳轉的頁面 let navParams = new Array(); params.forEach((v, i) => { if (i > 3) { navParams.push(v) } }); let navParamsObj = {};//拼接成要轉規定的參數模式 navParams.forEach((v, i) => { let item = 'p' + i; navParamsObj[item] = v; }); if (this.isLogin) { if (navPush == 'usercenter') { //導航頁面 this.navCtrl.parent.select(3); this.navCtrl.popToRoot(); } else { //二級頁面 //如果存在Local的話,再次進入也不會跳轉到分享出去的頁面,所以存在session this.ss.store('SHAREURLLOADED', true);//標識用戶是否已經跳轉過分享出去的頁面。//避免頁面刷新重復看到應用啟動的效果。 this.navCtrl.push(navPush, navParamsObj);//解析成為頁面跳轉需要的數據格式。 } } }, 500) } }
20170927:補充
import { Injectable } from '@angular/core';
import { URLSearchParams } from '@angular/http';
class environment {
static yxt = 'https://www1.hxyxt.com/';//正式環境
}
const URLS = {
'wechatConfig':'http://vipapi.yxtmart.cn/SIGN?url={url}',//獲取微信配置的數據
}
@Injectable()
export class URLService {
constructor() { }
getUrl(pathName: string, ...args) {
//頁面請求的參數處理
let reg = /^(http|https):\/\//;
let isUrl = reg.test(pathName)
if (isUrl && args.length == 0) return pathName;
pathName = isUrl ? pathName : URLS[pathName];
var url = pathName;for (var key in args[0]) {
url = url.replace(`{${key}}`, args[0][key]);
}
return url;
}
objectToUrlParams(obj) {
var paras = new URLSearchParams();
for (var key in obj) {
var element = obj[key];
paras.append(key, element)
}
return paras;
}
}
import { Injectable } from '@angular/core';
@Injectable()
export class CommonService {
constructor() { }
IsWeChatFun() {
//判斷是否在微信端
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i)) {
return true;
} else {
return false;
}
}
}
