改造起點
github L6zt
- 專案前端與後端緊耦合,分享資訊 放在jsp裡,例如:
<script>
window.$shareInformation = {
title: `....`,
desc: `.....`,
link: `.....`,
}
</script>
前端還要獲取全域性變數裡的值,初始化分享
2.分享功能沒有進行統一的合併,所以每個頁面都需要重寫分享邏輯,很low低效的很,而且不利於維護。
3.每次都需要 引入 釘釘 和 微信 分享的 sdk js 感覺浪費流量,而且 影響頁面載入速度, 這個兩個js都需要同時引入。
技術細節
對以上問題解決方案,我採用:
端對端懶載入 不同平臺的 sdk, 分享邏輯 統一由後端控制 即 頁面裡 只需要引入一個js指令碼。
總體引用方法
// data-ajax 放置獲取分享資訊 ajax的入參
//data-exclud 排除 不需要 那種分享
<script src="/js/share.js" data-ajax="{`a`: `1`, `b`: `2`}" data-exclud="[`wx`, `dd`]" data-slector="share"></script>
。。。。。。部分程式碼
公共函式
var noop = function() {};
var hasOwnP = function(obj, prop) {
return Object.hasOwnProperty.call(obj, prop);
};
var toString = function(obj) {
return Object.prototype.toString.call(obj);
};
var isHardVar = function(obj) {
var result = toString(obj);
return result === `[object Object]` || result === `[object Array]`;
}
var merge = function() {
var lg = arguments.length;
var result = {};
if (lg < 2) {
return arguments[0]
};
for (var i = 0; i < lg; i++) {
for (var key in arguments[i]) {
console.log(hasOwnP(arguments[i], key), key);
if (hasOwnP(arguments[i], key)) {
var value = arguments[i][key];
result[key] = value;
}
}
}
return result;
};
對非同步處理 自己模擬的promise實現
var JcPromise = (function() {
function JcPromise(fn) {
fn = fn || noop;
var statusList = [`start`, `pending`, `succeed`, `err`];
var cbStatus = [0, 1];
var status = statusList[0];
var data = null;
var err = null;
var that = this;
var successFn = [];
var errFn = [];
function resolve(d) {
data = d;
that._changeStatus(2);
};
function reject(e) {
err = e;
that._changeStatus(3);
};
this.getData = function() {
return data;
};
this.getErr = function() {
return err
};
this.getStatus = function() {
return status
};
this._changeStatus = function(idx) {
switch (status) {
case statusList[2]:
case statusList[3]:
{
return false
}
};
status = statusList[idx];
if (status === statusList[3]) {
setTimeout(function() {
that._triggerCatch();
}, 0)
}
if (status === statusList[2]) {
setTimeout(function() {
that._triggerThen();
}, 0)
}
};
this._pushThenCb = function(cb) {
successFn.push({
status: cbStatus[0],
cb: cb
});
if (status === statusList[2]) {
this._triggerThen();
}
};
this._pushCatchCb = function(cb) {
errFn.push({
status: cbStatus[0],
cb: cb
});
if (status === statusList[3]) {
this._triggerCatch();
}
};
this._triggerThen = function() {
successFn.map(function(item) {
if (item.status === cbStatus[0]) {
item.cb(data);
item.status = cbStatus[1];
}
})
};
this._triggerCatch = function() {
errFn.map(function(item) {
if (item.status === cbStatus[0]) {
item.cb(err);
item.status = cbStatus[1];
}
})
};
this._changeStatus(1);
this.uuid = uuid++;
try {
fn(resolve, reject);
} catch (e) {
reject(e)
}
return this
};
JcPromise.fn = JcPromise.prototype;
// 返回一個promise
JcPromise.fn.then = function(cb) {
var promiseR = null;
var promiseJ = null;
var result = null;
var that = this;
var fn = function() {
setTimeout(function() {
try {
var data = that.getData();
result = cb(data);
if (typeof result === `object` && result !== null && result.constructor === JcPromise) {
result.then(function(data) {
promiseR(data)
}).catch(function(e) {
promiseJ(e)
})
} else {
promiseR(result)
}
} catch (e) {
promiseJ(e)
}
}, 0);
};
this._pushThenCb(fn);
// 觸發promise
return new JcPromise(function(r, j) {
promiseR = r;
promiseJ = j;
});
};
// 返回一個promise
JcPromise.fn.catch = function(cb) {
var promiseR = null;
var promiseJ = null;
var result = null;
var that = this;
var fn = function() {
setTimeout(function() {
try {
var data = that.getErr();
result = cb(data);
if (typeof result === `object` && result !== null && result.constructor === JcPromise) {
result.then(function(data) {
promiseR(data)
}).catch(function(e) {
promiseJ(e)
})
} else {
promiseR(result)
}
} catch (e) {
promiseJ(e)
}
}, 0)
};
this._pushCatchCb(fn);
// 觸發promise
return new JcPromise(function(r, j) {
promiseR = r;
promiseJ = j;
});
};
return JcPromise
})();
懶載入載入js方法
function loadScript(src) {
return new JcPromise(function(r, j) {
var el = document.createElement(`script`);
el.onload = function() {
r(el);
};
el.onerror = function() {
j();
};
el.src = src;
document.body.appendChild(el);
});
};
判斷 是釘?還是微信
function checkIsWx() {
var userAgent = global.navigator.userAgent;
var checkWx = /MicroMessenger/i;
var splitWxVersion = /MicroMessenger/([d.]+)/i;
var version = 0;
var flag = false;
if (checkWx.test(userAgent)) {
flag = true;
version = splitWxVersion.exec(userAgent)[1];
version = parseFloat(version.replace(`.`, ``));
}
return {
type: `wx`,
flag: flag,
version: version
}
};
// 檢查是不是釘釘
function checkIsDd() {
var userAgent = global.navigator.userAgent;
var checkDd = /DingTalk/i;
var splitDdVersion = /DingTalk/([a-zA-Z0-9.-]+)/;
var version = 0;
var flag = false;
if (checkDd.test(userAgent)) {
flag = true;
version = splitDdVersion.exec(userAgent)[1];
}
return {
type: `dd`,
flag: flag,
version: version
}
};
// 自己照著 mdn 和其他文件 寫的 ajax
var jcAjax = (function() {
/*
@data
@type
@url
@setHeader
@createXhr
*/
function jcAjax(options) {
var defaultHeaders = {
`X-Requested-With`: `XMLHttpRequest`
};
var type = options.type,
headers = options.headers,
data = options.data,
cb = options.cb,
url = options.url,
data = options.data;
this.defaultHeaders = defaultHeaders;
this.type = (type || `get`).toUpperCase();
this.headers = options.headers || {};
this.cb = cb || noop;
this.url = url;
this.data = data || {};
this.init();
};
jcAjax.fn = jcAjax.prototype;
jcAjax.fn.setRequestHeader = function() {
var headers = this.headers;
var defaultHeaders = this.defaultHeaders;
var xhr = this.xhr;
var type = this.type;
this.headers = headers = merge(defaultHeaders, headers);
type === `POST` && !headers[`Content-Type`] && (headers[`Content-Type`] = `application/x-www-form-urlencoded`);
if (headers) {
for (var key in headers) {
if (hasOwnP(headers, key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
}
};
jcAjax.fn.createXhr = function() {
this.xhr = new XMLHttpRequest();
};
jcAjax.fn.listenAjax = function() {
var xhr = this.xhr;
var cb = this.cb;
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
cb(data)
}
};
};
jcAjax.fn.openHttp = function(type, url) {
var xhr = this.xhr;
xhr.open(type, url);
};
jcAjax.fn.sendData = function(data) {
var xhr = this.xhr;
var type = this.type;
data = data || null;
type === `GET` && (data === null)
xhr.send(data);
};
jcAjax.fn.transSendData = function() {
var result = null;
var headers = this.headers;
var contentType = headers[`Content-Type`];
var data = this.data;
switch (contentType) {
case `multipart/form-data`:
{
result = new FormData();
for (var key in data) {
var value = data[key];
if (hasOwnP(data, key)) {
result.append(key, value)
}
}
return result;
}
case `application/json`:
{
result = data;
return result
}
default:
{
result = ``;
for (var key in data) {
var value = data[key];
if (hasOwnP(data, key)) {
isHardVar(value) && (value = JSON.stringify(value))
result = result + key + `=` + value + `&`
}
}
result = result.replace(/&$/, ``)
return result
}
}
};
jcAjax.fn.get = function() {
var data = this.data;
var url = this.url;
var mdUrl = ``;
for (var key in data) {
var value = data[key];
if (hasOwnP(data, key)) {
mdUrl = mdUrl + encodeURIComponent(key) + `=` + encodeURIComponent(value) + `&`
}
}
mdUrl.replace(/&$/, ``);
this.createXhr();
this.openHttp(`GET`, mdUrl);
this.setRequestHeader();
this.listenAjax();
this.sendData();
};
jcAjax.fn.post = function() {
var sendData = null;
var url = this.url;
console.log(url);
this.createXhr();
this.openHttp(`POST`, url);
this.setRequestHeader();
this.listenAjax();
sendData = this.transSendData();
this.sendData(sendData);
};
jcAjax.fn.init = function() {
var type = this.type.toLowerCase();
this[type]();
}
return function(options) {
return new jcAjax(options);
}
})()
微信分享 釘?分享具體 api
// 微信分享 由版本問題相容問題
function wxShare(baseConfig, shareData, wxJsVersion) {
function findWxSupportApi(wxJsVersion) {
var jsApiList = null;
var bindEvent = null;
var api = null;
switch (wxJsVersion) {
case 1.3:
{
api = `onMenuShareTimeline|onMenuShareAppMessage|onMenuShareQQ|onMenuShareWeibo|onMenuShareQZone`;
jsApiList = api.split(`|`);
bindEvent = api.split(`|`);
break;
}
case 1.4:
{
api = `updateAppMessageShareData|updateTimelineShareData|onMenuShareWeibo`;
jsApiList = api.split(`|`);
bindEvent = api.split(`|`);
break;
}
};
return {
jsApiList: jsApiList,
bindEvent: bindEvent
}
};
var wxSupport = findWxSupportApi(wxJsVersion);
var jsApiList = wxSupport.jsApiList;
var bindEvent = wxSupport.bindEvent;
var title = shareData.title;
var desc = shareData.desc;
var link = shareData.link;
var imgUrl = shareData.imgUrl;
wx.config({
appId: baseConfig.appId,
timestamp: baseConfig.timestamp,
nonceStr: baseConfig.nonceStr,
signature: baseConfig.signature,
jsApiList: jsApiList
});
wx.ready(function() {
bindEvent.forEach(function(key) {
console.log(key);
wx[key] && wx[key]({
title,
desc,
link,
imgUrl,
success() {
var fnKey = key + `TriggerSuccess`;
var cb = wxShareTriggerCb[fnKey];
cb && cb();
},
error() {
var fnKey = key + `TriggerError`;
var cb = wxShareTriggerCb[fnKey];
cb && cb();
}
})
})
})
};
function ddShare(shareMsgData) {
dd.ready(function() {
var title = shareMsgData.title;
var desc = shareMsgData.desc;
var link = shareMsgData.link;
var imgUrl = shareMsgData.imgUrl;
dd.biz.navigation.setRight({
show: true,
control: true,
onSuccess: function(result) {
dd.biz.util.share({
url: link,
title: title,
content: desc,
image: imgUrl
});
}
})
});
};
初始化分享
function initShare() {
try {
ajaxData = eval(`(` + getAttr(scriptElem, `data-ajax`) + `)`);
excludeUa = eval(`(` + getAttr(scriptElem, `data-exclude`) + `)`) || [];
} catch (e) {
console.log(e)
}
if (isWx.flag && excludeUa.indexOf(`wx`) === -1) {
var wxVersion = isWx.version;
var wxUrl = null;
var wxJsVersion = 0;
if (wxVersion >= 672) {
wxUrl = `//res.wx.qq.com/open/js/jweixin-1.4.0.js`;
wxJsVersion = 1.4;
} else {
wxUrl = `//res.wx.qq.com/open/js/jweixin-1.3.0.js`;
wxJsVersion = 1.3;
}
loadScript(wxUrl).then(function(data) {
// 獲取 微信簽名 --- 不知本公司那個屌絲想
return loadScript(getWxShareSignatureApi)
}).then(function(baseConfig) {
getShareUserMsg(ajaxData).then(function(data) {
var shareFrom = data.shareH5Form;
var shareData = {
title: shareFrom.title,
link: shareFrom.link,
imgUrl: shareFrom.msgImg,
desc: shareFrom.desc
};
wxShare(global.weixinConfigInfo, shareData, wxJsVersion);
hadGetShareMsgHook(data);
})
})
}
if (isDd.flag && excludeUa.indexOf(`dd`) === -1) {
loadScript(ddUrl).then(function(data) {
//獲取分享資訊
getShareUserMsg(ajaxData).then(function(data) {
var shareFrom = data.shareH5Form;
var shareData = {
title: shareFrom.title,
link: shareFrom.link,
imgUrl: shareFrom.msgImg,
desc: shareFrom.desc
};
ddShare(shareData)
hadGetShareMsgHook(data)
})
})
}
}