使用iframe实现多个页面之间的切换(iframe高度自适应)

5 篇文章 0 订阅
5 篇文章 0 订阅

一、效果展示

在这里插入图片描述

二、实现代码

1、ListSet对象

if (typeof ListSet != 'undefined') {
        delete ListSet;
    }
    /**
     *
     * @param eleId
     * @param navs [{text: '',url: '',attributes: {}, style:{}, number:'', show: true},{text: '',url: '',attributes: {}, style:{}, number:'', show:true}]
     * @returns {ListSet}
     * @constructor
     */
    var ListSet = function ({
                                eleId,
                                navs = [],
                                navHeight = 80,
                                navScrollHeight = 0,
                                iframeHeight = '100vh',
                                iframeWidth = '100%',
                                forceIframeHeight = false,
                            }) {
        if (!eleId) {
            throw new Error('未设置根节点元素');
        }
        if (!navs.length) {
            throw new Error('未设置nav菜单');
        }
        this._rootElement = document.getElementById(eleId);
        if (!this._rootElement) {
            throw new Error('未找到根节点元素');
        }
        this._iframeH = iframeHeight;
        this._iframeW = iframeWidth;
        this._forceIframeH = forceIframeHeight;

        this._rangeKey = Math.ceil(Math.random() * 10000);
        this._scrollBox = document.createElement('div');
        this._navElement = document.createElement('ul');
        this._iframeElement = document.createElement('div');
        this._activeIframe = 0;
        this._navs = navs;
        this._navItems = [];
        this._iframes = [];
        this._loading = null;
        this._isMove = false;
        this._scrollBox.append(this._navElement);
        this._rootElement.append(this._scrollBox);
        this._rootElement.append(this._iframeElement);
        this._iframeElement.style = `position:relative;
                                     border-top: 3px solid rgba(0,0,0,0.3);
                                     overflow: auto;
                                     -webkit-border-radius: 3px 3px 0px 0px;
                                     -moz-border-radius: 3px 3px 0px 0px;
                                     border-radius: 3px 3px 0px 0px;`;
        this._navElement.style = `   width: calc(100% + 40px);
                                     height: ${navHeight}px;
                                     overflow: scroll;
                                     padding: 0px 10px;
                                     margin-left: -10px;
                                     display: flex;
                                     flex-wrap: nowrap;`;
        let scrollH = this._scrollBox.scrollHeight - this._scrollBox.offsetHeight;
        if (navScrollHeight > 2 * scrollH) {
            navScrollHeight = 2 * scrollH;
        }else if(navScrollHeight < 0){
        	navScrollHeight = 0;
        }
        this._scrollBox.style = `    width: 100%;
                                     height: ${navHeight - scrollH * 2 + navScrollHeight}px;
                                     overflow: hidden;
                                     margin-bottom: 5px;`;
        scrollH = this._scrollBox.scrollHeight - this._scrollBox.offsetHeight;
        this.initNavs();
        this.createIframe();
        this.eventListener();
        return this;
    }

2、添加横向滑动事件(滚动)

ListSet.prototype.eventListener = function () {
        let isDown = false, downX = 0, startX = this._navElement.scrollLeft;
        if (this._navElement.addEventListener) {
            this._navElement.addEventListener('mousedown', (e) => {
                isDown = true;
                downX = e.screenX;
                startX = this._navElement.scrollLeft
            });
            this._navElement.addEventListener('mousemove', (e) => {
                if (isDown) {
                    let distance = e.screenX - downX;
                    this._navElement.scrollTo(-distance + startX, 0);
                    if (Math.abs(distance) > 100) {
                        this._isMove = true;
                    }
                }
            });
            this._navElement.addEventListener('mouseup', (e) => {
                isDown = false;
            });
            this._navElement.addEventListener('mouseleave', (e) => {
                isDown = false;
                this._isMove = false;
            })
        }
    }

3、添加加载效果展示

ListSet.prototype.loading = function () {
        let n = 0;
        if (!this._loading) {
            this._loading = document.createElement('div');
            this._loading.style = ` display:none;
                                    width: 100%;
                                    position: absolute;
                                    top: 0px;
                                    left: 0px;
                                    z-index: 100;`;
            this._iframeElement.insertBefore(this._loading, this._iframes[0]);
            let ul = document.createElement('ul'), lis = [];
            ul.style = `width: 100%;
                        height: 200px;
                        display:flex;
                        justify-content: center;
                        align-items: center;
                        background:white;`;
            this._loading.append(ul);
            for (var i = 0; i < 3; i++) {
                var li = document.createElement('li');
                li.style = `width: 15px;
                            list-style: none;
                            height: 15px;
                            -webkit-border-radius: 15px;
                            -moz-border-radius: 15px;
                            border-radius: 15px;
                            border: 1px solid #ccc;
                            background: #ddd;
                            margin: 0px 10px;`;
                ul.append(li);
                lis.push(li);
            }
            this._loadingLis = lis;
        }
        this._iframes[this._activeIframe].style.visibility = 'hidden';
        try {
            this._iframes[this._activeIframe].contentWindow.location.reload(true);
        } catch (e) {
            this._iframes[this._activeIframe].src = this._navs[this._activeIframe].url;
        }
        this._loading.style.display = 'block';
        if (this._loadingHandle) clearInterval(this._loadingHandle);
        this._loadingHandle = setInterval(() => {
            this._loadingLis.forEach((li, i) => {
                if (i == n) {
                    li.style.background = 'red';
                } else {
                    li.style.background = '#ddd';
                }
            })
            n++;
            if (n >= this._loadingLis.length) {
                n = 0;
            }
        }, 100);
        return this;
    }

4、关闭加载效果

 ListSet.prototype.loaded = function () {
        if (this._loading) {
            this._loading.style.display = 'none';
            clearInterval(this._loadingHandle);
            this._loadingHandle = null;
        }
    }

5、创建tabs导航栏

ListSet.prototype.initNavs = function () {
        let w = 0, tw = this._navElement.clientWidth;
        this._navElement.classList.value = 'list-nav-box';
        this._navs.forEach((item, index) => {
            if (!item.text || !item.url) {
                throw new Error(item.text ? '未设置请求url' : '未设置nav菜单文本')
            }
            if (item.show) {
                let li = document.createElement('li');
                li.style = `list-style: none;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            padding: 10px 30px;
                            background: #b4bbc5;
                            flex-wrap: nowrap;
                            margin: 0px 1px;
                            cursor: pointer;
                            min-width: 200px;`;
                this._navElement.append(li);
                li.innerHTML = `<span>${item.text}</span><span">${item.num ? item.num : ''}</span>`;
                if (item.attributes) {
                    for (var attrName in item.attributes) {
                        li.setAttribute(attrName, item.attributes[attrName]);
                    }
                }
                if (item.style) {
                    for (var name in item.style) {
                        li.style[name] = item.style[name];
                    }
                }
                li.addEventListener('mouseup', (e) => {
                    if (this._isMove) {
                        this._isMove = false;
                        return false;
                    }
                    this._activeIframe = index;
                    this._iframes.forEach((iframe, i) => {
                        if (i == index) {
                            iframe.style.display = 'block';
                        } else {
                            iframe.style.display = 'none';
                        }
                    });
                    if (!this._iframes[index]) {
                        this.createIframe();
                    } else {
                        if (this._forceIframeH) {
                            this._iframes[index].style.height = this._iframeH;
                        } else {
                            try {
                                this._iframes[index].style.height = this._iframes[index].contentWindow.document.body.scrollHeight + 'px';
                            } catch (e) {
                                this._iframes[index].style.height = this._iframeH;
                            }
                        }
                    }
                    this._navItems.forEach((liItem, j) => {
                        if (j == index) {
                            liItem.style.background = '#f2f2f2';
                        } else {
                            liItem.style.background = '#b4bbc5';
                        }
                    })
                });

                li.addEventListener('dblclick', (e) => {
                    if (this._activeIframe == index) {
                        this.loading();
                    }
                })
                if (!this._navItems.length) {
                    this._activeIframe = index;
                }
                this._navItems[index] = li;
            }
        })
        return this;
    }

6、创建iframe窗口(高度自适应 内容高度)

    ListSet.prototype.createIframe = function () {
        let frame = document.createElement('iframe'), item = this._navs[this._activeIframe];
        frame.style = `width: ${this._iframeW};
                       height: ${this._iframeH};
                       border: 0px;
                       visibility: visible;`;
        frame.src = item.url;
        frame.name = 'iframe' + this._activeIframe;

        frame.onload = () => {
            if (this._forceIframeH) {
                frame.style.height = this._iframeH;
            } else {
                try {
                    // frame.contentWindow.onbeforeunload = function () {
                    //     // todo:: 加载完成前执行
                    //     frame.style.height = 'auto';
                    // };
                    frame.style.height = frame.contentWindow.document.body.scrollHeight + 'px';
                } catch (e) {
                    frame.style.height = this._iframeH;
                }
            }

            frame.style.visibility = 'visible';
            this.loaded();
        };
        this._navItems[this._activeIframe].style.background = '#f2f2f2';
        this._iframeElement.append(frame);
        this._iframes[this._activeIframe] = frame;
        this.loading();
        return this;
    }

7、完整代码

if (typeof ListSet != 'undefined') {
    delete ListSet;
}
/**
 *
 * @param eleId
 * @param navs [{text: '',url: '',attributes: {}, style:{}},{text: '',url: '',attributes: {}, style:{}}]
 * @returns {ListSet}
 * @constructor
 */
var ListSet = function ({
                            eleId,
                            navs = [],
                            scrollMode = false,
                            navHeight = 80,
                            navScrollHeight = 0,
                            iframeHeight = '100vh',
                            iframeWidth = '100%',
                            forceIframeHeight = false,
                            clickEvent = null,
                            iframeBeforeOnLoad = null,
                            iframeAfterOnLoad = null,
                        }) {
    if (!eleId) {
        throw new Error('未设置根节点元素');
    }
    if (!navs.length) {
        throw new Error('未设置nav菜单');
    }
    this._scrollMode = scrollMode;
    this._rootElement = document.getElementById(eleId);
    if (!this._rootElement) {
        throw new Error('未找到根节点元素');
    }
    this._iframeH = iframeHeight;
    this._iframeW = iframeWidth;
    this._forceIframeH = forceIframeHeight;

    this._rangeKey = Math.ceil(Math.random() * 10000);
    this._scrollBox = document.createElement('div');
    this._navElement = document.createElement('ul');
    this._iframeElement = document.createElement('div');
    this._activeIframe = 0;
    this._navs = navs;
    this._clickEvent = clickEvent;
    this._iframeAfterOnLoad = iframeAfterOnLoad;
    this._iframeBeforeOnLoad = iframeBeforeOnLoad;
    this._navItems = [];
    this._iframes = [];
    this._loading = null;
    this._isMove = false;
    this._scrollBox.append(this._navElement);
    this._rootElement.append(this._scrollBox);
    this._rootElement.append(this._iframeElement);
    this._navElement.classList.add('multi-window-nav-box');
    this._iframeElement.classList.add('multi-window-iframe-box');
    this._scrollBox.classList.add('multi-window-scroll-div');
    let scrollH = this._scrollBox.scrollHeight - this._scrollBox.offsetHeight;
    if (navScrollHeight > 2 * scrollH) {
        navScrollHeight = 2 * scrollH;
    } else if (navScrollHeight < 0) {
        navScrollHeight = 0;
    }
    scrollH = this._scrollBox.scrollHeight - this._scrollBox.offsetHeight;
    this.initStyle({
        navHeight: scrollMode ? (navHeight + "px") : "auto",
        navOverflow: scrollMode ? "scroll" : "auto",
        navFlexWrap: scrollMode ? "nowrap" : "wrap",
        scrollHeight: scrollMode ? (navHeight - scrollH * 2 + navScrollHeight) + "px" : "auto",
    })
    this.initNavs();
    this.createIframe();
    this.eventListener();
    return this;
}
ListSet.prototype.initStyle = function ({
                                            navHeight = 'auto',
                                            navOverflow = 'auto',
                                            navFlexWrap = 'wrap',
                                            scrollHeight = 'auto',

                                        }) {
    let style = document.createElement('style');
    style.innerHTML = `
        .multi-window-nav-box{
            width: calc(100% + 40px);
            padding: 0px 10px 0px 0px;
            display: flex;
            margin: 0px;
            height: ${navHeight};
            overflow: ${navOverflow};
            flex-wrap: ${navFlexWrap};
        }
        .multi-window-nav-box > .multi-window-nav-item{
            list-style: none;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 10px 25px;
            width: 14%;
            min-width: 160px;
            flex-wrap: nowrap;
            margin: ${this._scrollMode ? 0 : 1}px 1px;
            cursor: pointer;
            background: #b4bbc5;
            font-size: 14px;
        }
        .multi-window-nav-active{
            background: rgb(242, 242, 242) !important;
            color: red !important;
            font-weight: bold;
            font-size: 16px;
        }
        .multi-window-iframe-box{  
            position:relative;
            border-top: 3px solid rgba(0, 0, 0, 0.3);
            -webkit-border-radius: 3px 3px 0px 0px;
            -moz-border-radius: 3px 3px 0px 0px;
            border-radius: 3px 3px 0px 0px;
        }
        .multi-window-iframe-box > iframe{
            width: ${this._iframeW};
            height: ${this._iframeH};
            border: 0px;
            visibility: visible;
        }
        .multi-window-scroll-div{
            width: 100%;
            overflow: hidden;
            margin: 2px 0px;
            height: ${scrollHeight};
        }
        .multi-window-loading{
            display:none;
            width: 100%;
            position: absolute;
            top: 0px;
            left: 0px;
            z-index: 100;
        }
        .multi-window-loading > ul{
            width: 100%;
            height: 200px;
            display:flex;
            justify-content: center;
            align-items: center;
            background:white;
        }
        .multi-window-loading > ul > li{
            width: 15px;
            list-style: none;
            height: 15px;
            -webkit-border-radius: 15px;
            -moz-border-radius: 15px;
            border-radius: 15px;
            border: 1px solid #ccc;
            background: #ddd;
            margin: 0px 10px;
        }
    `;
    document.querySelector('head').append(style);
    return this;
}

ListSet.prototype.eventListener = function () {
    let isDown = false, downX = 0, startX = this._navElement.scrollLeft;
    if (this._navElement.addEventListener) {
        this._navElement.addEventListener('mousedown', (e) => {
            isDown = true;
            downX = e.screenX;
            startX = this._navElement.scrollLeft
        });
        this._navElement.addEventListener('mousemove', (e) => {
            if (isDown) {
                let distance = e.screenX - downX;
                this._navElement.scrollTo(-distance + startX, 0);
                if (Math.abs(distance) > 100) {
                    this._isMove = true;
                }
            }
        });
        this._navElement.addEventListener('mouseup', (e) => {
            isDown = false;
        });
        this._navElement.addEventListener('mouseleave', (e) => {
            isDown = false;
            this._isMove = false;
        })
    }
}

ListSet.prototype.loading = function () {
    let n = 0;
    if (!this._loading) {
        this._loading = document.createElement('div');
        this._loading.classList.add('multi-window-loading');
        this._iframeElement.insertBefore(this._loading, this._iframes[0]);
        let ul = document.createElement('ul'), lis = [];
        this._loading.append(ul);
        for (var i = 0; i < 3; i++) {
            var li = document.createElement('li');
            ul.append(li);
            lis.push(li);
        }
        this._loadingLis = lis;
    }
    this._iframes[this._activeIframe].style.visibility = 'hidden';
    try {
        this._iframes[this._activeIframe].contentWindow.location.reload(true);
    } catch (e) {
        this._iframes[this._activeIframe].src = this._navs[this._activeIframe].url;
    }
    this._loading.style.display = 'block';
    if (this._loadingHandle) clearInterval(this._loadingHandle);
    this._loadingHandle = setInterval(() => {
        this._loadingLis.forEach((li, i) => {
            if (i == n) {
                li.style.background = 'red';
            } else {
                li.style.background = '#ddd';
            }
        })
        n++;
        if (n >= this._loadingLis.length) {
            n = 0;
        }
    }, 100);
    return this;
}

ListSet.prototype.loaded = function () {
    if (this._loading) {
        this._loading.style.display = 'none';
        clearInterval(this._loadingHandle);
        this._loadingHandle = null;
    }
}

ListSet.prototype.initNavs = function () {
    let w = 0, tw = this._navElement.clientWidth;
    this._navs.forEach((item, index) => {
        if (!item.text || !item.url) {
            throw new Error(item.text ? '未设置请求url' : '未设置nav菜单文本')
        }
        if (typeof item['show'] == 'undefined' || item.show) {
            let li = document.createElement('li');
            li.classList.add('multi-window-nav-item')
            this._navElement.append(li);
            li.innerHTML = `<span>${item.text}</span>${item.num ? "<span>" + item.num + "</span>" : ''}`;
            if (item.attributes) {
                for (var attrName in item.attributes) {
                    li.setAttribute(attrName, item.attributes[attrName]);
                }
            }
            if (item.style) {
                for (var name in item.style) {
                    li.style[name] = item.style[name];
                }
            }
            li.addEventListener('mouseup', (e) => {
                if (this._clickEvent) {
                    this._clickEvent.call(this, e, item, index)
                }
                if (this._isMove) {
                    this._isMove = false;
                    return false;
                }
                this._activeIframe = index;
                this._iframes.forEach((iframe, i) => {
                    if (i == index) {
                        iframe.style.display = 'block';
                    } else {
                        iframe.style.display = 'none';
                    }
                });
                if (!this._iframes[index]) {
                    this.createIframe();
                } else {
                    if (this._forceIframeH) {
                        this._iframes[index].style.height = this._iframeH;
                    } else {
                        try {
                            this._iframes[index].style.height = this._iframes[index].contentWindow.document.body.scrollHeight + 'px';
                        } catch (e) {
                            this._iframes[index].style.height = this._iframeH;
                        }
                    }
                }
                this._navItems.forEach((liItem, j) => {
                    if (j == index) {
                        liItem.classList.add('multi-window-nav-active');
                    } else {
                        liItem.classList.remove('multi-window-nav-active');
                    }
                })
            });

            li.addEventListener('dblclick', (e) => {
                if (this._activeIframe == index) {
                    this.loading();
                }
            })
            if (!this._navItems.length) {
                this._activeIframe = index;
            }
            this._navItems[index] = li;
        }
    })
    return this;
}

ListSet.prototype.createIframe = function () {
    let frame = document.createElement('iframe'), item = this._navs[this._activeIframe];
    frame.src = item.url;
    frame.name = 'iframe' + this._activeIframe;

    frame.onload = (event) => {
        // console.log(222, event)
        if (this._iframeAfterOnLoad) {
            this._iframeAfterOnLoad.call(this, item);
        }
        if (this._forceIframeH) {
            // frame.style.height = this._iframeH;
            if (this._iframeBeforeOnLoad) {
                this._iframeBeforeOnLoad.call(this, item);
            }
        } else {
            try {
                frame.contentWindow.onbeforeunload = (e) => {
                    // console.log(1111, e)
                    // todo:: 加载完成前执行
                    if (this._iframeBeforeOnLoad) {
                        this._iframeBeforeOnLoad.call(this, item);
                    }
                };
                // frame.style.height = (frame.contentWindow.document.body.scrollHeight) + 'px';
            } catch (e) {
                // frame.style.height = this._iframeH;
                if (this._iframeBeforeOnLoad) {
                    this._iframeBeforeOnLoad.call(this, item);
                }
            }
        }
        frame.style.visibility = 'visible';
        this.loaded();
    };
    this._navItems[this._activeIframe].classList.add('multi-window-nav-active');
    this._iframeElement.append(frame);
    this._iframes[this._activeIframe] = frame;
    this.loading();
    return this;
}


function iframeCall({
                        callback = null,
                        fireOptions = null,
                        confirmCallback = null,
                        cancelCallback = null,
                        errorCallback = null,
                        callThis = null,
                    }) {
    if (fireOptions) {
        swal.fire(fireOptions).then((isConfirm) => {
            try {
                if (isConfirm.value) {
                    confirmCallback && confirmCallback.call(callThis ? callThis : this);
                } else {
                    cancelCallback && cancelCallback.call(callThis ? callThis : this);
                }
            } catch (e) {
                errorCallback && errorCallback.call(callThis ? callThis : this, e);
            }
        })
    }
    if (callback) {
        if (typeof callback == 'string') {
            eval('var fn = ' + callback);
            fn.call(callThis ? callThis : this);
        } else {
            callback.call(callThis ? callThis : this);
        }
    }
}

三、Example

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #list-set-box {
            width: 100%;
            overflow: auto;
            padding-top: 10px;
        }
    </style>
</head>
<body>
	<section id="list-set-box"></section>
</body>
</html>
let listSet = new ListSet({
        eleId: 'list-set-box',
        navHeight = 80,
        navScrollHeight = 0,
        iframeHeight = '100vh',
        iframeWidth = '100%',
        forceIframeHeight = false,
        navs: [
        	{
        		text:'百度',
        		url:'https://www.baidu.com',
        		show: true,
        		num:'<span style="color:red;">(10)</span>',
        		attributes: {},
        		style:{}
        	},{
        		text:'淘宝',
        		url:'https://www.taobao.com',
        		show: true,
        		num:'',
        		attributes: {},
        		style:{}
        	},{
        		text:'京东',
        		url:'https://www.jd.com',
        		show: true,
        		num:'',
        		attributes: {},
        		style:{}
        	}
        ],
    })

四、总结经验

至此,完美的实现多个页面之间的切换。
(注意:如果iframe的src是跨域路径,无法获取document.body的高度,所以无法实现iframe自适应高度,可以通过设置固定的iframeHeight值,默认为100vh )
以上内容希望能够帮助到有需要的博友们!!!
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以使用JavaScript实现多个iframe自适应高度的效果。下面是一个简单的示例代码: ```html <!DOCTYPE html> <html> <head> <title>多个iframe自适应高度</title> <style> .iframe-container { position: relative; padding-bottom: 56.25%; /* 这里假设iframe的宽高比为16:9,可以根据实际情况进行调整 */ height: 0; overflow: hidden; } .iframe-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } </style> </head> <body> <div class="iframe-container"> <iframe src="https://example.com" frameborder="0" allowfullscreen></iframe> </div> <div class="iframe-container"> <iframe src="https://example.org" frameborder="0" allowfullscreen></iframe> </div> <script> function resizeIframe(iframe) { iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px'; } window.addEventListener('DOMContentLoaded', function() { var iframes = document.getElementsByTagName('iframe'); for (var i = 0; i < iframes.length; i++) { iframes[i].addEventListener('load', function() { resizeIframe(this); }); } }); </script> </body> </html> ``` 在上面的示例代码中,我们使用了CSS来创建了一个具有固定宽高比的容器,然后将每个iframe放置在这个容器内。通过设置容器的padding-bottom为一个百分比值,可以确保iframe高度按比例自适应。通过JavaScript的load事件监听,当每个iframe加载完成后,调用resizeIframe函数来动态设置iframe高度,以适应其内容的高度。 您可以根据实际情况,修改代码中的iframe的src属性和容器的样式。这样,多个iframe就可以根据各自内容的高度自适应显示了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值