js 原生面向对象(OOP)封装选项卡插件2.0

https://www.jq22.com/webqd7329(线上展示地址)

//功能包括 上拉分页加载,tab切换,过渡动画切换,点击、上拉事件回调,自动切换tab,设置时间

 

index.js
;(function(global) {
    "use strict";
    let deferTimer;
    var M = function(el, options) {
        this.el = typeof el === "string" ? document.querySelector(el) : el;
        this.options = JSON.stringify(options) != '{}' ? options : false;
        if (this.options) {
            this.options.contentIndex = JSON.stringify(options) != '{}' ? 0 : false;
        };
        this.options && this.tabTitle();
    };
    M.prototype = {
        addtod: function() {
            console.log(this)
            return this
        },
        //样式设置
        setStyle: function(dom, objStyle) {
            for (var k in objStyle) {
                dom.style[k] = objStyle[k];
            };
        },
        // 初始化创建tab,并且绑定事件回调
        tabTitle: function() {
            let type = typeof this.options.Title[0];
            let _this = this;

            for (var i = 0; i <= this.options.Title.length - 1; i++) {
                let li = document.createElement("li");
                li.start = i;

                li.data = this.options.Title[i];
                var textnode = (type === 'string' && document.createTextNode(`${this.options.Title[i]}`)) || (type === 'object' && document.createTextNode(`${this.options.Title[i].name}`));
                li.onclick = function() {
                    _this.liEvent(this)
                };
                li.appendChild(textnode);
                this.el.appendChild(li);
            };

            (this.options.defaultIndex && this.defaultIndexEvetn(this.options.defaultIndex - 1)) || (!this.options.defaultIndex && this.defaultIndexEvetn(0))

            // 是否开启上拉监听
            typeof this.options.handleScroll === 'function' && this.options.content && this.MonitorBox();

            // 是否开启自动切换
            this.options.automatic && this.options.automatic.open && this.switchAutomatic();
            // console.log(this)
        },
        liEvent(that) {
            if (this.options.contentIndex == that.start) {
                return;
            };
            for (var k = this.el.getElementsByTagName("li").length - 1; k >= 0; k--) {
                this.el.getElementsByTagName("li")[k].className = '';
            };
            this.options.contentIndex = that.start;
            this.options.MonitorSubscript = that.start;
            that.className = 'active';
            this.options.content && this.contentEvetn(that.start);
            this.options.titleEvent && this.options.titleEvent(that.data);
        },
        // 自动切换
        switchAutomatic() {
            let dataChildren = getChildren(this.el);
            let index = this.options.defaultIndex;
            let that = this;
            let time = Number(this.options.automatic.time) && this.options.automatic.time > 0 ? Number(this.options.automatic.time) : false;
            setInterval(function() {
                if (index == dataChildren.length) {
                    index = 0;
                };
                that.liEvent(dataChildren[index]);
                index++;
            }, time ? time : 2500);
        },
        // 默认展示第几项
        defaultIndexEvetn: function(activeDom) {
            let _this = this;
            this.el.getElementsByTagName("li")[activeDom].className = 'active';
            // 记录上次选项卡标题下标
            this.options.contentIndex = activeDom;
            let content = this.options.content ? document.getElementById(this.options.content) : false;

            let dataChildren = content && getChildren(content);
            if (this.options.content && !this.options.transition) { //是否有内容容器切换,有就设置默认选项
                for (var i = 0; i < dataChildren.length; i++) {
                    dataChildren[i].style.cssText = `overflow-y: auto;`;
                };
                dataChildren[activeDom].style.display = 'block';
                // 记录上次展示的容器下标
                this.options.index = activeDom;

            } else if (this.options.content && this.options.transition) {
                let w = this.el.offsetWidth;
                for (var i = 0; i < dataChildren.length; i++) {
                    dataChildren[i].style.display = 'block';
                    dataChildren[i].style.cssText = `width: ${w}px; float: left; padding: 0px; margin: 0px; vertical-align: top; display: table-cell;overflow-y: auto;`
                };

                content.style.cssText = `overflow: hidden; position: relative;width: ${w*content.getElementsByTagName('div').length}px;transform: translate3d(-${w*activeDom}px, 0px, 0px);-webkit-transform: translate3d(-${w*activeDom}px, 0px, 0px);-o-transition:translate3d(-${w*activeDom}px, 0px, 0px);transition:translate3d(-${w*activeDom}px, 0px, 0px);`;
                let style = {
                    'transition': `all ${this.options.transitionTime||0.3}s ease-in-out 0s`,
                    '-webkit-transition': `all ${this.options.transitionTime||0.3}s ease-in-out 0s`,
                    '-o-transition': `all ${this.options.transitionTime||0.3}s ease-in-out 0s`,
                };
                this.setStyle(content, style);
                this.contentEvetn(activeDom);
                this.options.index = activeDom;
            };


            // 是否开启上拉监听 开启后默认用户选中的tab
            (typeof this.options.handleScroll === 'function') && dataChildren && (dataChildren[activeDom].addEventListener('scroll', function() {
                _this.handleScroll.call(this, _this);
            }, true));
        },
        // 切换内容
        contentEvetn: function(index) {
            if (index == this.options.index) {
                return;
            };
            let content = document.getElementById(this.options.content);
            let content1 = getChildren(content);
            if (this.options.transition) {
                let w = this.el.offsetWidth;
                // 对当前5个版本做兼容
                let style = {
                    'transition': `all ${this.options.transitionTime||0.3}s ease-in-out 0s`,
                    '-webkit-transition': `all ${this.options.transitionTime||0.3}s ease-in-out 0s`,
                    '-o-transition': `all ${this.options.transitionTime||0.3}s ease-in-out 0s`,
                    'transform': `translate3d(-${w*index}px, 0px, 0px)`,
                    '-webkit-transform': `translate3d(-${w*index}px, 0px, 0px)`,
                };
                this.setStyle(content, style);
            } else {
                content1[this.options.index].style.display = 'none';
                content1[index].style.display = 'block';
            };
            this.options.index = index;
        },
        // 滚动监听
        handleScroll: function(that) {
       //节流触发  clearTimeout(deferTimer); deferTimer
= setTimeout(() => { var scrollTop = this.scrollTop; //变量windowHeight是可视区的高度 var windowHeight = this.clientHeight; //变量scrollHeight是滚动条的总高度 var scrollHeight = this.scrollHeight; let scroll = { scrollTop, windowHeight, scrollHeight }; //滚动条到底部的条件 if (scrollTop + windowHeight == scrollHeight) { that.options.handleScroll(scroll); } else if ((parseInt(scrollTop) + 1) + windowHeight == scrollHeight) { //这里在写一个判断是因为scrollTop到底部可能是小数 因此取整数 scroll.scrollTop = parseInt(scrollTop + 1) that.options.handleScroll(scroll); }; }, 350); } }; // 上拉-监听 M.prototype.MonitorBox = function() { let content = document.getElementById(this.options.content); let dataChildren = getChildren(content); let _this = this; Object.defineProperty(_this.options, 'MonitorSubscript', { get: function() { return MonitorSubscript }, set: function(newValue) { dataChildren[newValue].addEventListener('scroll', function() { _this.handleScroll.call(this, _this); }, true); } }); }; // 获取父下子第一级子元素 function getChildren(obj) { var objChild = []; var objs = obj.getElementsByTagName('*'); for (var i = 0, j = objs.length; i < j; ++i) { if (objs[i].nodeType != 1) { alert(objs[i].nodeType); continue; }; var temp = objs[i].parentNode; if (temp.nodeType == 1) { if (temp == obj) { objChild[objChild.length] = objs[i]; }; } else if (temp.parentNode == obj) { objChild[objChild.length] = objs[i]; }; }; return objChild; }; if (typeof module !== 'undefined' && module.exports) module.exports = M; if (typeof define === 'function') define(function() { return M; }); global.tabBar = M; })(this);

 

 

 

HTML

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>马丁的车夫</title>
    </head>
    <style type="text/css">
        ul,
        li {
            list-style: none;
            flex: 1;
            text-align: center;
            cursor: pointer;
            padding: 5px 0;
        }

        ul {
            display: flex;
            margin: 0;
            padding: 0;
        }

        .div {
            width: 100%;
            overflow: hidden;
            background-color: #80b600;
        }

        .active {
            background-color: #80b600;
            color: #ffffff;
        }

        #tabClick {
            background-color: #f5f5f5;
            color: #80b600;
        }

        #content>div {
            display: none;
            height: 200px;
        }

        #tabClick1 {
            background-color: #f5f5f5;
            color: #80b600;
        }

        #content1>div {
            display: none;
            height: 200px;
        }

        #tabClick2 {
            background-color: #f5f5f5;
            color: #80b600;
        }

        #content2>div {
            display: none;
            height: 200px;
        }

        #tabClick3 {
            background-color: #f5f5f5;
            color: #80b600;
        }

        #content3>div {
            display: none;
            height: 200px;
        }

        /* ------------ */
        .box {
            display: flex;
            justify-content: center;
        }

        h2 {
            text-align: center;
        }
    </style>
    <body>
        <div class="box">
            <div>
                <h2>模式一:基础tab点击切换</h2>
                <div style="width: 500px;margin-top: 30px;">
                    <div class="div">
                        <ul id="tabClick"></ul>
                        <div id="content">
                            <div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                            </div>
                            <div>
                                <div>222</div>
                                <div>111</div>
                                <div>111</div>
                            </div>
                            <div>333</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="box">
            <div>
                <h2>模式二:点击过渡滑动切换动画</h2>
                <div style="width: 500px;margin-top: 30px;">
                    <div class="div">
                        <ul id="tabClick1"></ul>
                        <div id="content1">
                            <div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                            </div>
                            <div>
                                <div>222</div>
                                <div>111</div>
                            </div>
                            <div>333</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="box">
            <div>
                <h2>模式三:1.滑动底部加载更多触发回调函数,2.点击选项卡触发回调函数</h2>
                <div style="width: 500px;margin-top: 30px; margin-left: auto;margin-right: auto;">
                    <div class="div">
                        <ul id="tabClick2"></ul>
                        <div id="content2">
                            <div id="tab1">
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div style="text-align: center;margin-bottom: 20px;">上拉加载更多</div>
                            </div>
                            <div>
                                <div>222</div>

                            </div>
                            <div>333</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="box">
            <div>
                <h2>模式四:自动切换tab,设置时间</h2>
                <div style="width: 500px;margin-top: 30px; margin-left: auto;margin-right: auto;">
                    <div class="div">
                        <ul id="tabClick3"></ul>
                        <div id="content3">
                            <div id="oop">
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>
                                <div>111</div>

                            </div>
                            <div>
                                <div>222</div>

                            </div>
                            <div>333</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <script src="./index.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            /**
             * @overview
             * 选项卡功能包括 
             *         1.tabBar切换
             *         2.默认展示具体第几项
             *         3.上拉底部加载更多事件回调触发
             *         4.切换选项卡过渡动画设置
             * 设置参数
             * @param Title :[string,string]/[{name:'value'}] 设置tab切换按钮标题
             *           content :string 切换内容父级容器id节点名称
             *           defaultIndex :number 默认选中第几项
             *           titleEvent :EventHandle 点击选项卡事件回调
             *           transition :Boolean 是否开启切换过度动画,默认0.3s
             *           handleScroll :EventHandle 当前容器上拉滚动条到底部监听
             *           transitionTime :number 设置过渡动画时间
             *             automatic:{ 
                            open:true, Boolean 是否开启自动切换
                            time:3000    number     设置自动切换时间,不设置默认2500
                        }
             */
            // 模式一
            let a1 = new tabBar("#tabClick", {
                Title: [{
                        name: 'Tab1',
                        id: 1
                    },
                    {
                        name: 'Tab2',
                        id: 2
                    },
                    {
                        name: 'Tab3',
                        id: 3
                    }
                ], //选卡标题数据格式Title:['首页']/或者Title:[{name:'首页'}]
                content: 'content',
            });
            // 模式二
            let a2 = new tabBar("#tabClick1", {
                Title: [{
                        name: 'Tab1',
                        id: 1
                    },
                    {
                        name: 'Tab2',
                        id: 2
                    },
                    {
                        name: 'Tab3',
                        id: 3
                    }
                ], //选卡标题数据格式Title:['首页']/或者Title:[{name:'首页'}]
                content: 'content1',
                transition: true,
                transitionTime: 0.4
            });

            let index = 1; //页数
            // 模式三
            let a3 = new tabBar("#tabClick2", {
                Title: [{
                        name: 'Tab1',
                        id: 1
                    },
                    {
                        name: 'Tab2',
                        id: 2
                    },
                    {
                        name: 'Tab3',
                        id: 3
                    }
                ], //选卡标题数据格式Title:['首页']/或者Title:[{name:'首页'}]
                content: 'content2',
                transition: true,
                defaultIndex: 1,
                titleEvent: function(tabIndex) {
                    // console.log(tabIndex,'==')
                    alert('当前点击了' + tabIndex.name)
                },
                handleScroll: function(res) {
                    // console.log("距顶部" + scrollTop + "可视区高度" + windowHeight + "滚动条总高度" + scrollHeight);
                    alert('到底部了')
                    let content2 = document.getElementById("tab1");
                    if (index < 50) {
                        for (var i = 0; i < 10; i++) {
                            let div = document.createElement("div");
                            let textnode = document.createTextNode(`加载更多的数据${index}`)
                            div.appendChild(textnode);
                            content2.appendChild(div);
                            index++;
                        };
                    };
                    // console.log(content2)
                }
            });

            // 模式四
            let a4 = new tabBar("#tabClick3", {
                Title: [{
                        name: 'Tab1',
                        id: 1
                    },
                    {
                        name: 'Tab2',
                        id: 2
                    },
                    {
                        name: 'Tab3',
                        id: 3
                    }
                ], //选卡标题数据格式Title:['首页']/或者Title:[{name:'首页'}]
                content: 'content3',
                transition: true,
                defaultIndex: 1,
                automatic: {
                    open: true,
                    time: 1000
                }
            });
        </script>
    </body>
</html>

我是马丁的车夫,欢迎转发收藏!

 

posted on 2021-03-05 11:21  马丁的车夫  阅读(100)  评论(0)    收藏  举报