点击iframe中的链接时,使用历史记录pushState更改父窗口的URL

转载自:https://www.codenong.com/35518763/   (该文章明显来自stackoverflow的一篇问答,存在一些翻译上的问题,我们能理解即可)

我有一个页面,该页面的标题和侧边栏带有正确的内容面板(即iframe)。

在加载到右侧内容面板的页面中,我试图单击链接将父窗口中的浏览器URL更新为加载到iframe中的新页面的URL。

我不希望实际的父窗口重新加载URL,而只是更新地址栏中的URL。

就像是:

window.history.pushState('obj', 'newtitle', '/bookmarks/list/');

是否可以通过iframe使用?

相关讨论

  • "这是来自iframe的可能性吗?" 您是否尝试过这种方法?
  • @ guest271314我已经尝试过,它更新了iframe的网址,因此我的iframe加载了新页面并拥有了新网址,但父网址从未更改
  • 我想我将尝试使用iframe onmessage事件从iframe发送新网址给父级,并在父页面中,从父级调用window.history.pushState,看看是否能起到魔力
  • 见stackoverflow.com/questions/33645685/
  • @ guest271314那个帖子是要更改页面的内容。 我需要更新URL而不重新加载页面。 上面发布的想法可行。 我的父母使用发布消息接收URL,然后发送pushState更新父母URL

 通过使用postMessage从子Iframe窗口向父级发送新URL并在侦听此事件的父窗口上,我可以使用history.pushState完成地址栏中的父窗口URL更新。

当父级收到子级iframe postMessage事件时,它将使用该消息中传递的URL使用pushSTate更新URL。

子iframe

// Detect if this page is loaded inside an Iframe window
function inIframe() {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

// Detect if the CTRL key is pressed to be used when CTRL+Clicking a link
$(document).keydown(function(event){
    if(event.which=="17")
        cntrlIsPressed = true;
});
$(document).keyup(function(){
    cntrlIsPressed = false;
});
var cntrlIsPressed = false;

// check if page is loaded inside an Iframe?
if(inIframe()){
    // is the CTRL key pressed?
    if(cntrlIsPressed){
        // CTRL key is pressed, so link will open in a new tab/window so no need to append the URL of the link
    }else{

        // click even on links that are clicked without the CTRL key pressed
        $('a').on('click', function() {

            // is this link local on the same domain as this page is?
            if( window.location.hostname === this.hostname ) {

                // new URL with ?sidebar=no appended to the URL of local links that are clicked on inside of an iframe
                var linkUrl = $(this).attr('href');
                var noSidebarUrl = $(this).attr('href')+'?sidebar=no';

                // send URL to parent window
                parent.window.postMessage('message-for-parent=' +linkUrl , '*');

                alert('load URL with no sidebar: '+noSidebarUrl+' and update URL in arent window to: '+linkUrl);

                // load Iframe with clicked on URL content
                //document.location.href = url;
                //return false;
            }
        });
    }
}

父窗口 

// parent_on_message(e) will handle the reception of postMessages (a.k.a. cross-document messaging or XDM).
function parent_on_message(e) {
    // You really should check origin for security reasons
    // https://developer.mozilla.org/en-US/docs/DOM/window.postMessage#Security_concerns
    //if (e.origin.search(/^http[s]?:\\/\\/.*\\.localhost/) != -1
    //    && !($.browser.msie && $.browser.version <= 7)) {
        var returned_pair = e.data.split('=');
        if (returned_pair.length != 2){
            return;
        }
        if (returned_pair[0] === 'message-for-parent') {
            alert(returned_pair[1]);
            window.history.pushState('obj', 'newtitle', returned_pair[1]);
        }else{
            console.log("Parent received invalid message");
        }

    //}
}

jQuery(document).ready(function($) {
    // Setup XDM listener (except for IE < 8)
    if (!($.browser.msie && $.browser.version <= 7)) {
        // Connect the parent_on_message(e) handler function to the receive postMessage event
        if (window.addEventListener){
            window.addEventListener("message", parent_on_message, false);
        }else{
            window.attachEvent("onmessage", parent_on_message);
        }
    }
});

使用Window.postMessage()的另一种解决方案。 

iframe:

/test
/test2


Array.from(document.querySelectorAll('a')).forEach(el => {
  el.addEventListener('click', event => {
    event.preventDefault();
    window.parent.postMessage(this.href, '*');
  });
});

 主页:

Current URL:
<iframe src="iframe-url"></iframe>


const $currentUrl = document.querySelector('#current-url');
$currentUrl.textContent = location.href;

window.addEventListener('message', event => {
  history.pushState(null, null, event.data);
  $currentUrl.textContent = event.data;
});

参见JS Fiddle上的演示。

无论是否使用History API,都可以使用这种方法来检测iframe的网址更改。

setInterval(function() {

    var iframeUrl = document.getElementById("the-iframe").contentWindow.location.href;

    if (window.lastIframeUrl !== iframeUrl) {
        console.log("iframe url changed", iframeUrl);
        window.lastIframeUrl = iframeUrl
    }

}, 100)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值