renren开源导航栏点击同一菜单不刷新页面问题

最近一个项目使用了renren-security这个开源框架,先纵览一下外观,
renren开源导航栏点击同一菜单不刷新页面问题_第1张图片

嗯,确认过眼神,是传统管理后台的样子~

使用过程中发现,当在导航栏中点击同一菜单时,iframe并不会刷新,其实这也不算个问题,奈何产品经理就要这个功能,只好看看人家源码是怎么写的了,很容易在index.js中就找到了控制路由的代码(真正的开源应当如此**):

function routerList(router, menuList) {
    for (var key in menuList) {
        var menu = menuList[key];
        if (menu.type == 0) {
            routerList(router, menu.list);
        } else if (menu.type == 1) {
            router.add('#' + menu.url, function () {
                var url = window.location.hash;
                //替换iframe的url
                vm.main = url.replace('#', '');
                //导航菜单展开
                $(".treeview-menu li").removeClass("active");
                $("a[href='" + url + "']").parents("li").addClass("active");
                vm.navTitle = $("a[href='" + url + "']").text();
            });
        }
    }
}

很明显,这是一个递归算法,将所有菜单逐层“注册”,通过menu.type来区分是父菜单(无跳转)还是子菜单(需要跳转),并对需要跳转的子菜单添加了回调方法,触发条件就是’#’ + menu.url。此时,大家应该明白为何点击同一菜单不刷新页面了,因为浏览器中的链接跟’#’ + menu.url还是一致的,所以就不会触发回调。
找到了问题所在,那就好下手解决了,分两步走:
1.同一菜单也要触发回调
2.iframe的主动刷新
我们发现替换iframe的url是window.location.hash,首先了解一下window.location.hash和window.location.href。
window.location.href:对应完整的url,可以跳转页面,也可以获取链接
window.location.hash:获取或设置锚链接,不会跳转页面
知道了以上,我们就能解决1了,在每次触发回调后将当前页面的锚链接修改一下,这样保证浏览器中的链接跟注册的’#’ + menu.url不一致,那么怎样修改链接还能保持是同一个页面呢?显然,加时间戳参数:

window.location.hash=url+"?t="+new Date().getTime();

再来解决2,此时虽然点击同一菜单都会触发回调了,但是vm.main = url.replace(’#’, ‘’)取到的url始终是同一个,表现到页面上就是,浏览器地址不断在刷新,但是iframe并没有刷新,所以我们需要主动刷新iframe。
由于iframe是嵌套在index.html中的,这里需要在父页面来刷新子页面,给iframe一个定义一个id为childIframe,通过以下代码来刷新iframe:

$("#childIframe")[0].contentWindow.location.reload(true)

如果你没有用JQuery,也可以用原生写法:

document.getElementById('childIframe').contentWindow.location.reload(true);

以上2步,就实现了点击同一菜单也刷新页面的功能,但是在使用中发现,如果在一个iframe中通过window.location.href跳转了新页面,那么再点击同一菜单的时候,刷新的是二级页面,造成这个问题的原因很简单,因为window.location.href已经改变了浏览器中的地址,vm.main得到的是二级页面的地址,所以在跳转二级页面的时候,我们不使用window.location.href,而是给vm.main赋二级页面的地址,并且刷新iframe,此时虽然跳转到了二级页面,但是浏览器中的地址并没有变化,再点击同一菜单,自然会刷新一级页面。
在index.js中抽象出一个统一的跳转方法:

function goNext(url) {
    vm.main = url;
    $("#childIframe")[0].contentWindow.location.reload(true);
}

在需要跳转的地方通过parent对象来调用父页面的这个goNext方法:

parent.goNext("modules/**/**.html?t="+new Date().getTime());

重新整合一下routerList方法:

function routerList(router, menuList) {
    for (var key in menuList) {
        var menu = menuList[key];
        if (menu.type == 0) {
            routerList(router, menu.list);
        } else if (menu.type == 1) {
            router.add('#' + menu.url, function () {
                var url = window.location.hash;
                   //替换iframe的url
                    goNext(url.replace('#', ''));
                   $(".treeview-menu li").removeClass("active");
                   $("a[href='" + url + "']").parents("li").addClass("active");
                   vm.navTitle = $("a[href='" + url + "']").text();
                   window.location.hash=url+"?t="+new Date().getTime();
            });
        }
    }
}

你可能感兴趣的:(前端)