5

改造起点

github L6zt

  1. 项目前端与后端紧耦合,分享信息 放在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)
                })
            })
        }
    }

方糖先生
1.1k 声望1.8k 粉丝