美文网首页IT@程序员猿媛
常用的JavaScript方法封装

常用的JavaScript方法封装

作者: Abellll | 来源:发表于2019-04-01 19:14 被阅读1次
    /**
     * 存储localStorage
     */
    export const setStore = (name, content) => {
        if (!name) return;
        if (typeof content !== 'string') {
            content = JSON.stringify(content);
        }
        window.localStorage.setItem(name, content);
    }
    
    /**
     * 获取localStorage
     */
    export const getStore = name => {
        if (!name) return;
        return window.localStorage.getItem(name);
    }
    
    /**
     * 删除localStorage
     */
    export const removeStore = name => {
        if (!name) return;
        window.localStorage.removeItem(name);
    }
    
    /**
     * 获取style样式
     */
    export const getStyle = (element, attr, NumberMode = 'int') => {
        let target;
        // scrollTop 获取方式不同,没有它不属于style,而且只有document.body才能用
        if (attr === 'scrollTop') { 
            target = element.scrollTop;
        }else if(element.currentStyle){
            target = element.currentStyle[attr]; 
        }else{ 
            target = document.defaultView.getComputedStyle(element,null)[attr]; 
        }
        //在获取 opactiy 时需要获取小数 parseFloat
        return  NumberMode == 'float'? parseFloat(target) : parseInt(target);
    } 
    
    /**
     * 页面到达底部,加载更多
     */
    export const loadMore = (element, callback) => {
        let windowHeight = window.screen.height;
        let height;
        let setTop;
        let paddingBottom;
        let marginBottom;
        let requestFram;
        let oldScrollTop;
    
        document.body.addEventListener('scroll',() => {
           loadMore();
        }, false)
        //运动开始时获取元素 高度 和 offseTop, pading, margin
        element.addEventListener('touchstart',() => {
            height = element.offsetHeight;
            setTop = element.offsetTop;
            paddingBottom = getStyle(element,'paddingBottom');
            marginBottom = getStyle(element,'marginBottom');
        },{passive: true})
    
        //运动过程中保持监听 scrollTop 的值判断是否到达底部
        element.addEventListener('touchmove',() => {
           loadMore();
        },{passive: true})
    
        //运动结束时判断是否有惯性运动,惯性运动结束判断是非到达底部
        element.addEventListener('touchend',() => {
            oldScrollTop = document.body.scrollTop;
            moveEnd();
        },{passive: true})
        
        const moveEnd = () => {
            requestFram = requestAnimationFrame(() => {
                if (document.body.scrollTop != oldScrollTop) {
                    oldScrollTop = document.body.scrollTop;
                    loadMore();
                    moveEnd();
                }else{
                    cancelAnimationFrame(requestFram);
                    //为了防止鼠标抬起时已经渲染好数据从而导致重获取数据,应该重新获取dom高度
                    height = element.offsetHeight;
                    loadMore();
                }
            })
        }
    
        const loadMore = () => {
            if (document.body.scrollTop + windowHeight >= height + setTop + paddingBottom + marginBottom) {
                callback();
            }
        }
    }
    
    /**
     * 显示返回顶部按钮,开始、结束、运动 三个过程中调用函数判断是否达到目标点
     */
    export const showBack = callback => {
        let requestFram;
        let oldScrollTop;
    
        document.addEventListener('scroll',() => {
           showBackFun();
        }, false)
        document.addEventListener('touchstart',() => {
           showBackFun();
        },{passive: true})
    
        document.addEventListener('touchmove',() => {
           showBackFun();
        },{passive: true})
    
        document.addEventListener('touchend',() => {
            oldScrollTop = document.body.scrollTop;
            moveEnd();
        },{passive: true})
        
        const moveEnd = () => {
            requestFram = requestAnimationFrame(() => {
                if (document.body.scrollTop != oldScrollTop) {
                    oldScrollTop = document.body.scrollTop;
                    moveEnd();
                }else{
                    cancelAnimationFrame(requestFram);
                }
                showBackFun();
            })
        }
    
        //判断是否达到目标点
        const showBackFun = () => {
            if (document.body.scrollTop > 500) {
                callback(true);
            }else{
                callback(false);
            }
        }
    }
    
    
    /**
     * 运动效果
     * @param {HTMLElement} element   运动对象,必选
     * @param {JSON}        target    属性:目标值,必选
     * @param {number}      duration  运动时间,可选
     * @param {string}      mode      运动模式,可选
     * @param {function}    callback  可选,回调函数,链式动画
     */
    export const animate = (element, target, duration = 400, mode = 'ease-out', callback) => {
        clearInterval(element.timer);
    
        //判断不同参数的情况
        if (duration instanceof Function) {
            callback = duration;
            duration = 400;
        }else if(duration instanceof String){
            mode = duration;
            duration = 400;
        }
    
        //判断不同参数的情况
        if (mode instanceof Function) {
            callback = mode;
            mode = 'ease-out';
        }
    
        //获取dom样式
        const attrStyle = attr => {
            if (attr === "opacity") { 
                return Math.round(getStyle(element, attr, 'float') * 100);
            } else {
                return getStyle(element, attr);
            }
        }
        //根字体大小,需要从此将 rem 改成 px 进行运算
        const rootSize = parseFloat(document.documentElement.style.fontSize);
    
        const unit = {};
        const initState = {};
    
        //获取目标属性单位和初始样式值
        Object.keys(target).forEach(attr => {
            if (/[^\d^\.]+/gi.test(target[attr])) {
                unit[attr] = target[attr].match(/[^\d^\.]+/gi)[0] || 'px';
            }else{
                unit[attr] = 'px';
            }
            initState[attr] = attrStyle(attr);
        });
    
        //去掉传入的后缀单位
        Object.keys(target).forEach(attr => {
            if (unit[attr] == 'rem') {
                target[attr] = Math.ceil(parseInt(target[attr])*rootSize);
            }else{
                target[attr] = parseInt(target[attr]);
            }
        });
    
    
        let flag = true; //假设所有运动到达终点
        const remberSpeed = {};//记录上一个速度值,在ease-in模式下需要用到
        element.timer = setInterval(() => {
            Object.keys(target).forEach(attr => {
                let iSpeed = 0;  //步长
                let status = false; //是否仍需运动
                let iCurrent = attrStyle(attr) || 0; //当前元素属性址
                let speedBase = 0; //目标点需要减去的基础值,三种运动状态的值都不同
                let intervalTime; //将目标值分为多少步执行,数值越大,步长越小,运动时间越长
                switch(mode){
                    case 'ease-out': 
                        speedBase = iCurrent;
                        intervalTime = duration*5/400;
                        break;
                    case 'linear':
                        speedBase = initState[attr];
                        intervalTime = duration*20/400;
                        break;
                    case 'ease-in':
                        let oldspeed = remberSpeed[attr] || 0;
                        iSpeed = oldspeed + (target[attr] - initState[attr])/duration;
                        remberSpeed[attr] = iSpeed
                        break;
                    default:
                        speedBase = iCurrent;
                        intervalTime = duration*5/400; 
                }
                if (mode !== 'ease-in') {
                    iSpeed = (target[attr] - speedBase) / intervalTime;
                    iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                }
                //判断是否达步长之内的误差距离,如果到达说明到达目标点
                switch(mode){
                    case 'ease-out': 
                        status = iCurrent != target[attr]; 
                        break;
                    case 'linear':
                        status = Math.abs(Math.abs(iCurrent) - Math.abs(target[attr])) > Math.abs(iSpeed);
                        break;
                    case 'ease-in':
                        status = Math.abs(Math.abs(iCurrent) - Math.abs(target[attr])) > Math.abs(iSpeed);
                        break;
                    default:
                        status = iCurrent != target[attr]; 
                }
    
                if (status) {
                    flag = false; 
                    //opacity 和 scrollTop 需要特殊处理
                    if (attr === "opacity") {
                        element.style.filter = "alpha(opacity:" + (iCurrent + iSpeed) + ")";
                        element.style.opacity = (iCurrent + iSpeed) / 100;
                    } else if (attr === 'scrollTop') {
                        element.scrollTop = iCurrent + iSpeed;
                    }else{
                        element.style[attr] = iCurrent + iSpeed + 'px';
                    }
                } else {
                    flag = true;
                }
    
                if (flag) {
                    clearInterval(element.timer);
                    if (callback) {
                        callback();
                    }
                }
            })
        }, 20);
    }
    //使用  animate(document.body, {scrollTop: '0'}, 400,'ease-out');
    
    /*
     * cookie的封装
     */
    function getCookie(name)
    {
        var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
        if(arr=document.cookie.match(reg))
            return decodeURIComponentEx(arr[2]);
        else
            return null;
    }
    function setCookie(name,value)
    {
        var Days = 30;
        var exp = new Date();
        exp.setTime(exp.getTime() + Days*24*60*60*1000);
        document.cookie = name + "="+ escape (value) + ";expires="+exp.toGMTString()+";path=/; domain=.xiaoyeshouyin.com";
    }
    //删除cookies
    function delCookie(name)
    {
        var exp = new Date();
        exp.setTime(exp.getTime() - 1);
        var cval=getCookie(name);
        if(cval!=null)
            document.cookie= name + "="+cval+";expires="+exp.toGMTString()+";path=/; domain=.xiaoyeshouyin.com";
    }
    

    相关文章

      网友评论

        本文标题:常用的JavaScript方法封装

        本文链接:https://www.haomeiwen.com/subject/hnjbbqtx.html