• javascript 模拟亚马逊左侧导航算法的tab选项卡,支持四个方向,支持tab键切换,兼容各浏览器


    Javascript tab选项卡(一切为了更好的体验, God in details!!!)

    这原本只是一道简单的面试题,做出一个tab选项卡,然后要支持键盘TAB键控制。然后最近亚马逊的那个左侧菜单栏监听鼠标轨迹技术挺热门的,就把这功能添加进来了,而且还支持四个方向,用的都是原生js。如有问题,欢迎讨论

      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
    • 0002
    • 0003
    • 0004
    • 0005
    • 0006
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
    • 0002
    • 0003
    • 0004
    • 0005
    • 0006
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
      • 1
      • 1
      • 1
      • 1
      • 1
    • 2222
      2222
    • 3333
    • 4444
      2222
    • 0001
     
    <!DOCTYPE HTML>
    <html lang="en-US">
    <head>
        <meta charset="UTF-8">
        <title>Javascript tab选项卡</title>
        <style>
            #menu {
                float: left;
                padding: 0;
                margin-left: 20px;
            }
            #menu3 {
                float: right;
                padding: 0;
                margin-left: 20px;
            }
            #menu2 {
                overflow: hidden;
                zoom: 1;
            }
            #menu li, #menu3 li {
                 12em;
            }
            .menu {
                list-style: none;
                background: #bf8d04;
                margin: 0;
                padding: 0;
                overflow: hidden;
            }
            #menu2 li, #menu4 li {
                 8em;
                float: left;
            }
            .menu li.on {
                background: #ff6600;
            }
            #menu li a, #menu3 li a {
                height: 3em;
                line-height: 3em;
            }
            .menu li a {
                display: block;
                text-align: center;
            }
            #menu2 li a, #menu4 li a {
                height: 5em;
                line-height: 5em;
            }
            #tabCon {
                float: left;
                display: inline;
                margin-left: 1em;
            }
            #tabCon2 {
                height: 50em;
            }
            #tabCon3 {
                float: right;
            }
        </style>
    </head>
    <body>
    <div style="overflow:hidden;zoom:1;">
        <ul class="menu" id="menu">
            <li><a href="javascript:" data-href="#tab1">1</a></li>
            <li><a href="javascript:" data-href="#tab2">2</a></li>
            <li><a href="javascript:" data-href="#tab3">3</a></li>
            <li><a href="javascript:" data-href="#tab4">4</a></li>
            <li><a data-href="#tab5" href="javascript:">5</a></li>
            <li><a data-href="#tab6" href="javascript:">6</a></li>
            <li><a data-href="#tab7" href="javascript:">7</a></li>
            <li><a data-href="#tab8" href="javascript:">8</a></li>
            <li><a data-href="#tab9" href="javascript:">9</a></li>
            <li><a data-href="#tab10" href="javascript:">10</a></li>
            <li><a href="javascript:" data-href="#tab11">11</a></li>
            <li><a href="javascript:" data-href="#tab12">12</a></li>
            <li><a href="javascript:" data-href="#tab13">13</a></li>
            <li><a href="javascript:" data-href="#tab14">14</a></li>
            <li><a data-href="#tab15" href="javascript:">15</a></li>
        </ul>
        <ul id="tabCon">
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
            <li>0002</li>
            <li>0003</li>
            <li>0004</li>
            <li>0005</li>
            <li>0006</li>
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
        </ul>
    </div>
    
    <div>
        <ul class="menu" id="menu2">
            <li><a href="javascript:" data-href="#tab1">1</a></li>
            <li><a href="javascript:" data-href="#tab2">2</a></li>
            <li><a href="javascript:" data-href="#tab3">3</a></li>
            <li><a href="javascript:" data-href="#tab4">4</a></li>
            <li><a data-href="#tab5" href="javascript:">5</a></li>
            <li><a data-href="#tab6" href="javascript:">6</a></li>
            <li><a data-href="#tab7" href="javascript:">7</a></li>
            <li><a data-href="#tab8" href="javascript:">8</a></li>
            <li><a data-href="#tab9" href="javascript:">9</a></li>
            <li><a data-href="#tab10" href="javascript:">10</a></li>
        </ul>
        <ul id="tabCon2">
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
        </ul>
    </div>
    <div style="overflow:hidden;zoom:1;">
        <ul class="menu" id="menu3">
            <li><a href="javascript:" data-href="#tab1">1</a></li>
            <li><a href="javascript:" data-href="#tab2">2</a></li>
            <li><a href="javascript:" data-href="#tab3">3</a></li>
            <li><a href="javascript:" data-href="#tab4">4</a></li>
            <li><a data-href="#tab5" href="javascript:">5</a></li>
            <li><a data-href="#tab6" href="javascript:">6</a></li>
            <li><a data-href="#tab7" href="javascript:">7</a></li>
            <li><a data-href="#tab8" href="javascript:">8</a></li>
            <li><a data-href="#tab9" href="javascript:">9</a></li>
            <li><a data-href="#tab10" href="javascript:">10</a></li>
            <li><a href="javascript:" data-href="#tab11">11</a></li>
            <li><a href="javascript:" data-href="#tab12">12</a></li>
            <li><a href="javascript:" data-href="#tab13">13</a></li>
            <li><a href="javascript:" data-href="#tab14">14</a></li>
            <li><a data-href="#tab15" href="javascript:">15</a></li>
        </ul>
        <ul id="tabCon3">
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
            <li>0002</li>
            <li>0003</li>
            <li>0004</li>
            <li>0005</li>
            <li>0006</li>
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
        </ul>
    </div>
    
    <div>
        <ul style="height:200px;" id="tabCon4">
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
            <li>
                <ul>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                    <li>1</li>
                </ul>
            </li>
            <li>2222<br>2222</li>
            <li>3333</li>
            <li>4444<br>2222</li>
            <li>0001</li>
        </ul>
        <ul class="menu" id="menu4">
            <li><a href="javascript:" data-href="#tab1">1</a></li>
            <li><a href="javascript:" data-href="#tab2">2</a></li>
            <li><a href="javascript:" data-href="#tab3">3</a></li>
            <li><a href="javascript:" data-href="#tab4">4</a></li>
            <li><a data-href="#tab5" href="javascript:">5</a></li>
            <li><a data-href="#tab6" href="javascript:">6</a></li>
            <li><a data-href="#tab7" href="javascript:">7</a></li>
            <li><a data-href="#tab8" href="javascript:">8</a></li>
            <li><a data-href="#tab9" href="javascript:">9</a></li>
            <li><a data-href="#tab10" href="javascript:">10</a></li>
        </ul>
    
    </div>
    <div style="height:500px;"></div>
    <script>
        (function(window){
            /**
             * tab选项类
             * @param {String} eventType 事件类型,可以指定'click', 'mouseover'事件
             * @param {Element} menu 菜单包裹器元素,必须是ul或者ol的标签元素
             * @param {Element} container 选项卡包裹器内容,必须是ul或者ol的标签元素
             * @param {Boolean} TabKeyCtrl 是否开启键盘tab键控制,缺省为true,开启
             */
            var TabChange = function (eventType, menu, container, TabKeyCtrl) {
                this.eventType = eventType;
                this.menu = menu;
                this.container = container;
                // 菜单元素的链接数组
                this.menuLinks = menu.getElementsByTagName('a');
                // 设置延迟定时器,防止鼠标移到tab内容经过菜单时的切换
                this.timeout = null;
                // 记录鼠标移动时的坐标数组
                this.mouseLocs = [];
                // 菜单栏的固定点1, 根据菜单栏和内容的位置而改变
                this.firstSlope = null;
                // 菜单栏的固定点2, 根据菜单栏和内容的位置而改变
                this.secondSlope = null;
                // 记录内容栏相对于菜单栏的位置
                this.relatedPos = '';
                // 返回内容栏相对于菜单栏的位置, 保存在this.relatedPos属性里
                this.contentPosRelate();
                // 根据内容栏相对于菜单栏的位置, 返回菜单栏的固定点1,和固定点2
                this.ensureTriangleDots();
    
                // 默认开启TAB键控制
                TabKeyCtrl = TabKeyCtrl || true;
                if (TabKeyCtrl) {
                    // 启动tab键切换
                    this.tabKeyCtrl(this.menuLinks);
                }
                // 初始化事件
                this.initEvent();
            };
    
    
            TabChange.prototype = (function(){
                /**
                 * 显示隐藏切换方法
                 * @param {Array} elementArray 元素集数组,是tab内容li元素集
                 * @param {Number} index 当前序号
                 */
                var toggleDisplay = function (elementArray, index) {
                    // 显示当前序号的元素
                    elementArray[index].style.display = '';
                    // 隐藏非当前序号的元素
                    for (var i = 0, len = elementArray.length; i < len; i++) {
                        if (i === index) {
                            continue;
                        }
                        elementArray[i].style.display = 'none';
                    }
                };
    
                /**
                 * 获取元素相对于浏览器左上角的坐标位置,为正值
                 * @param element
                 * @return {{x: Number, y: Number}}
                 * @constructor
                 */
                var LocFromdoc = function (element) {
                    var left = element.offsetLeft,
                            top = element.offsetTop;
                    element = element.offsetParent;
                    while (element !== null) {
                        left += element.offsetLeft;
                        top += element.offsetTop;
                        element = element.offsetParent;
                    }
                    return {
                        x: left,
                        y: top
                    };
                };
    
                /**
                 * 类名转换方法,确保当前序号的类名,删除其他序号的类名
                 * @param {Array} elementArray 元素集数组 存放tab菜单li元素集
                 * @param {Number} index 当前序号
                 * @param {String} className 要添加的类名
                 */
                var toggleClass = function (elementArray, index, className) {
                    var pattern = new RegExp(' ' + className + ' ');
                    for (var i = 0, len = elementArray.length; i < len; i++) {
                        // 前后添加空格,且确保不能有连续空格
                        var temp = ' ' + elementArray[i].className.replace(/^\s+|\s+$/, '').replace(/\s+/, ' ') + ' ';
                        // 当前序号
                        if (i === index) {
                            // 如果当前序号的元素没有该类名,则添加类名
                            if (temp.indexOf(' ' + className + ' ') === -1) {
                                elementArray[i].className += (elementArray[i].className ? ' ' : '') + 'on';
                            }
                            // 跳到下一个循环
                            continue;
                        }
    
                        // 非当前序号,删除类名,去掉多余空格
                        elementArray[i].className = temp.replace(pattern, '').replace(/^\s+|\s+$/, '').replace(/\s+/, ' ');
                    }
                };
    
                return {
                    /**
                     * 根据内容栏相对于菜单栏的位置,判断移动过程中的点是否在三角形内
                     * @param {Object} p1 开始位置
                     * @param {Object} p2 菜单栏固定点1
                     * @param {Object} p3 菜单栏固定点2
                     * @param {Object} m 结束位置
                     * @return {*}
                     */
                    proPosInTriangle: function (p1, p2, p3, m) {
                        // 结束时鼠标坐标位置
                        var x = m.x,
                                y = m.y,
                        // 开始鼠标坐标位置
                                x1 = p1.x,
                                y1 = p1.y,
                        // 菜单栏包裹层右上角坐标
                                x2 = p2.x,
                                y2 = p2.y,
                        // 右下角坐标
                                x3 = p3.x,
                                y3 = p3.y,
                        // (y2 - y1) / (x2 - x1)为两坐标连成直线的斜率
                        // 因为直线的公式为y=kx+b;当斜率相同时,只要比较
                        // b1和b2的差值就可以知道该点是在
                        // (x1,y1),(x2,y2)的直线的哪个方向
                        // 当r1大于0,说明该点在直线右侧,其它以此类推
                                r1 = y - y1 - (y2 - y1) / (x2 - x1) * (x - x1),
                                r2 = y - y2 - (y3 - y2) / (x3 - x2) * (x - x2),
                                r3 = y - y3 - (y1 - y3) / (x1 - x3) * (x - x3),
                                compare;
    
                        // 根据位置不同,判定公式也不同,因为找不到通用的办法
                        // 只好各个对比
                        switch (this.relatedPos) {
                            case 'left':
                                compare = (r1 * r2 * r3 > 0) && (r1 > 0);
                                break;
                            case 'right':
                            case 'down':
                                compare = (r1 * r2 * r3 < 0) && (r1 > 0);
                                break;
                            case 'up':
                                compare = (r1 * r2 * r3 > 0) && (r1 < 0);
                                break;
                            default:
                                break;
                        }
                        // 返回是否在三角形内的结果
                        return compare;
                    },
                    /**
                     * 记录元素的位置信息
                     * @param element
                     * @return {{top: *, topAndHeight: number, left: *, leftAndWidth: number}}
                     */
                    info: function (element) {
                        var location = LocFromdoc(element);
                        return {
                            top: location.y,
                            topAndHeight: location.y + element.offsetHeight,
                            left: location.x,
                            leftAndWidth: location.x + element.offsetWidth
                        };
                    },
                    /**
                     * 记录内容栏相对于菜单栏的位置,因为后面还要用刀,使用this.relatedPos记录信息
                     * @param {Number} deviation 容许的差值,或者偏差
                     */
                    contentPosRelate: function (deviation) {
                        deviation = deviation || 0;
                        var ele1 = this.info(this.menu),
                                ele2 = this.info(this.container);
    
                        // ele2左边距离的浏览器左侧的距离大于
                        // ele1左边距离的浏览器左侧的距离加上本身的宽
                        // 说明ele2在ele1的右侧,其他以此类推
                        if (ele2.left >= (ele1.leftAndWidth + deviation)) {
                            this.relatedPos = 'right';
                        } else if (ele1.left >= (ele2.leftAndWidth + deviation)) {
                            this.relatedPos = 'left';
                        } else if (ele2.top >= (ele1.topAndHeight + deviation)) {
                            this.relatedPos = 'down';
                        } else if(ele1.top >= (ele2.topAndHeight + deviation)) {
                            this.relatedPos = 'up';
                        }
    
                    },
                    /**
                     * 根据内容栏相对于菜单栏的位置, 返回菜单栏的固定点1,和固定点2,保存在this.firstSlope和this.secondSlope对象里
                     */
                    ensureTriangleDots: function () {
                        var x1, y1, x2, y2;
                        var info = this.info(this.menu);
                        switch (this.relatedPos) {
                            case 'right':
                                x1 = info.leftAndWidth;
                                y1 = info.top;
                                x2 = x1;
                                y2 = info.topAndHeight;
                                break;
                            case 'left':
                                x1 = info.left;
                                y1 = info.top;
                                x2 = x1;
                                y2 = info.topAndHeight;
                                break;
                            case 'down':
                                x1 = info.left;
                                y1 = info.topAndHeight;
                                x2 = info.leftAndWidth;
                                y2 = y1;
                                break;
                            case 'up':
                                x1 = info.left;
                                y1 = info.top;
                                x2 = info.leftAndWidth;
                                y2 = y1;
                                break;
                            default:
                                break;
                        }
    
                        this.firstSlope = {
                            x: x1,
                            y: y1
                        };
                        this.secondSlope = {
                            x: x2,
                            y: y2
                        };
                    },
                    /**
                     * 键盘tab键控制tab菜单切换
                     * @param {Element} menuLinks tab菜单的链接数组,因为只有链接可以被键盘tab切换
                     */
                    tabKeyCtrl: function (menuLinks) {
                        var that = this;
                        // 侦听document的keyup事件
                        EventUtil.addEvent(document, 'keyup', function (event) {
                            event = EventUtil.getEvent(event);
                            // 获取当前元素
                            var target = EventUtil.getTarget(event),
                            // 获取当前元素的data-href属性
                                    href = target.getAttribute('data-href');
                            // 当按下的是tab键时且data-href属性值包含"#tab"字符
                            if ((event.keyCode === 9) && href && (href.indexOf('#tab') > -1)) {
                                // 获取对应数字,表示显示的tab菜单的相应序号
                                var index = parseInt(href.split('#tab')[1], 10) - 1;
                                // 触发当前序号的tab菜单事件,切换tab
                                EventUtil.triggerEvent(menuLinks[index], that.eventType);
                            }
                        });
    
                    },
                    /**
                     * 初始化事件,主要是注册tab菜单的事件侦听器
                     */
                    initEvent: function () {
                        var that = this,
                                menuLinks = this.menuLinks,
                                clickRegistration;
    
                        // 给tab菜单的链接注册侦听器
                        function toggle(array1, array2, index, className) {
                            // 类名切换
                            toggleClass(array1, index, className);
                            // 显示切换
                            toggleDisplay(array2, index);
                        }
    
                        for (var i = 0, len = menuLinks.length; i < len; i++) {
                            // 当为mouseover事件时,给mouseout注册事件侦听器
                            // 防止鼠标移到tab内容经过菜单时的切换
                            if (this.eventType === 'mouseover') {
                                EventUtil.addEvent(menuLinks[i], 'mouseover', (function (index) {
                                    return function (event) {
                                        // 捕捉第一次初始化的错误
                                        try {
                                            // 是否在指定三角形内
                                            var diff = that.proPosInTriangle(that.mouseLocs[0], that.firstSlope, that.secondSlope, that.mouseLocs[2]);
                                        } catch (ex) {
                                        }
    
                                        // 是就启动延迟显示,
                                        // 否则不延迟
                                        if (diff) {
                                            that.timeout = setTimeout(function () {
                                                toggle(that.menu.children, that.container.children, index, 'on');
                                            }, 300);
                                        } else {
                                            toggle(that.menu.children, that.container.children, index, 'on');
                                        }
                                    };
                                })(i));
                                // 记录鼠标在菜单栏中移动的最后三个坐标位置
                                EventUtil.addEvent(menuLinks[i], 'mousemove', function (event) {
                                    that.mouseLocs.push({
                                        x: EventUtil.eventPage(event).x,
                                        y: EventUtil.eventPage(event).y
                                    });
                                    if (that.mouseLocs.length > 3) {
                                        // 移除超过三项的数据
                                        that.mouseLocs.shift();
                                    }
                                });
    
                                // 鼠标移出的时候,清除延时器
                                EventUtil.addEvent(menuLinks[i], 'mouseout', function (event) {
                                    if (that.timeout) {
                                        clearTimeout(that.timeout);
                                    }
                                });
                            } else {
                                // 其它事件侦听器,例如“click”
                                EventUtil.addEvent(menuLinks[i], this.eventType, clickRegistration = (function (index) {
                                    return function (event) {
                                        clearTimeout(that.timeout);
                                        // 启动延时显示
                                        that.timeout = setTimeout(function () {
                                            toggle(that.menu.children, that.container.children, index, 'on');
                                        }, 80);
                                        // 阻止默认行为
                                        EventUtil.preventDefault(event);
                                    };
                                })(i));
                            }
                        }
    
                        // 触发第一个菜单链接的事件
                        EventUtil.triggerEvent(menuLinks[0], this.eventType);
                    }
                };
            }());
    
    
            /**
             * 跨浏览器event对象处理对象
             * @type {{addEvent: Function, getEvent: Function, getTarget: Function, preventDefault: Function, triggerEvent: Function}}
             */
            var EventUtil = {
                /**
                 * 注册事件侦听器
                 * @param element
                 * @param type
                 * @param listener
                 */
                addEvent: function (element, type, listener) {
                    if (element.addEventListener) {
                        element.addEventListener(type, listener, false);
                    } else {
                        element['e' + type + listener] = listener;
                        element[type + listener] = function () {
                            element['e' + type + listener](window.event);
                        };
                        element.attachEvent('on' + type, element[type + listener]);
                    }
                },
                removeEvent: function (element, type, listener) {
                    if (element.removeEventListener) {
                        //W3C 方法
                        element.removeEventListener(type, listener, false);
                        return true;
                    } else if (element.detachEvent) {
                        //MSIE方法
                        element.detachEvent("on" + type, element[type + listener]);
                        element['e' + type + listener] = null;
                        element[type + listener] = null;
                        return true;
                    }
                    //若两种方法都不具备则返回false
                    return false;
                },
                /**
                 * 获取event对象
                 * @param event
                 * @return {*|Event}
                 */
                getEvent: function (event) {
                    return event || window.event;
                },
                /**
                 * 获取目标元素
                 * @param event
                 * @return {EventTarget|Object}
                 */
                getTarget: function (event) {
                    event = this.getEvent(event);
                    return event.target || event.srcElement;
                },
                /**
                 * 阻止默认行为
                 * @param event
                 */
                preventDefault: function (event) {
                    event = this.getEvent(event);
                    if (event.preventDefault) {
                        event.preventDefault();
                    } else {
                        event.returnValue = false;
                    }
                },
                /**
                 * 触发事件
                 * @param element
                 * @param type
                 */
                triggerEvent: function (element, type) {
                    var ua = navigator.userAgent;
                    if (ua.indexOf('MSIE') && parseInt(ua.split('MSIE')[1], 10) < 9) {
                        element.fireEvent("on" + type);
                    } else {
                        var e = document.createEvent('MouseEvent');
                        e.initEvent(type, false, false);
                        element.dispatchEvent(e);
                    }
                },
                eventPage: function (event) {
                    event = this.getEvent(event);
                    return {
                        x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)),
                        y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop))
                    };
                }
            };
    
    
            var TabFactory = {
                create: function (eventType, menu, container, TabKeyCtrl) {
                    return new TabChange(eventType, menu, container, TabKeyCtrl);
                }
            };
    
            window.TabFactory = TabFactory;
        }(window));
    
    var menu = document.getElementById('menu'),
            container = document.getElementById('tabCon'),
            menu2 = document.getElementById('menu2'),
            container2 = document.getElementById('tabCon2'),
            menu3 = document.getElementById('menu3'),
            container3 = document.getElementById('tabCon3'),
            menu4 = document.getElementById('menu4'),
            container4 = document.getElementById('tabCon4');
    
    // 实例化对象
    TabFactory.create('mouseover', menu, container);
    TabFactory.create('mouseover', menu2, container2);
    TabFactory.create('mouseover', menu3, container3);
    TabFactory.create('mouseover', menu4, container4);
    </script>
    </body>
    </html> 
  • 相关阅读:
    多线程008如何预防死锁
    多线程003volatile的可见性和禁止指令重排序怎么实现的
    多线程011线程池运行原理及复用原理
    多线程010为什么要使用线程池
    多线程009什么是守护线程
    多线程005创建线程有哪些方式
    多线程007描述一下线程安全活跃态问题,以及竞态条件
    多线程002ThreadLocal有哪些内存泄露问题,如何避免
    关于Tomcat的启动时机(精通Eclipse Web开发P40)
    乱侃~~~
  • 原文地址:https://www.cnblogs.com/webFrontDev/p/2943994.html
Copyright © 2020-2023  润新知