后退或前进按钮后骨干视图未正确初始化

时间:2014-05-21 18:00:31

标签: javascript jquery ajax backbone.js

所以我有一个单页骨干应用程序,它通过AJAX加载到新页面,并使用历史API更新URL。这一切都运行正常,但是当我按下后退按钮时它只会更改URL并且不会加载以前的AJAX。

所以我已经开始解决这个问题,但我有一个奇怪的问题,即调用前面的AJAX,正确加载但不起作用,因为我收到以下错误:

this.el is undefined

我真的不知道如何解决这个问题,这是我的一些代码:

ContainerView = Backbone.View.extend({
el: 'body',
events: {
    'click .navigation-item': 'loadRequestedPage'
},
initialize: function() {
    this.listenTo(Backbone, 'popstate', this.onPopState);
},
onPopState: function(e) {
    var pageName = window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1, window.location.pathname.lastIndexOf('php') + 3);
    $('.navigation-item[href="'+pageName+'"]').eq(0).click();
},
....
loadRequestedPage: function(e) {
    if (Modernizr.history) {
        e.preventDefault();

        var pageModel = myWebsite.where({pageID: currentPage})[0],
            requestedPageID = $(e.currentTarget).data('page-id'),
            requestedPageModel = myWebsite.where({pageID: requestedPageID})[0],
            requestedPageUrl = requestedPageModel.get('pageUrl'),
            $targetElement = this.determineTargetElement(requestedPageID);

        this.closeMobileNavigation();

        this.loadNewPage(requestedPageModel, requestedPageUrl, requestedPageID, $targetElement);

        this.setActiveNavItem(requestedPageUrl);
        this.updateCurrentPage(requestedPageID);
        this.gaTrackEvent('Page Navigation', requestedPageUrl, 'User used the main navigation to navigate to' + requestedPageUrl);
    }
},

loadRequestedPage内的功能会继续触发history.pushstate,然后触发backbone.router,最后启动所需的view

在手动点击.navigation-item时工作正常但在点击后退按钮后通过JS触发时却没有。

如果有人能提供帮助那就太棒了。

感谢。

修改

这是我的路由器

var app = app || {};

(function($) {

    var Router = Backbone.Router.extend({
        routes: {
            '': 'instantiateHome',
            'index.php': 'instantiateHome',
            'our-approach.php': 'instantiateOurApproach',
            'our-work.php': 'instantiateOurWork',
            'people.php': 'instantiatePeople',
            'social.php': 'instantiateSocial',
            'contact-us.php': 'instantiateContactUs',
            "*notFound" : 'notFound'
        },
        instantiateHome: function() {    
            if(app.home_view == null) {
                app.home_view = new app.HomeView();
            }
        },
        instantiateOurApproach : function() {
            if(app.our_approach_view == null) {
                app.our_approach_view = new app.OurApproachView();
            }
        },
        instantiateOurWork: function() {
            if(app.our_work_view == null) {
                app.our_work_view = new app.OurWorkView();
            }
        },
        instantiatePeople: function() {
            if(app.people_view == null) {
                app.people_view = new app.PeopleView();
            }
        },
        instantiateSocial: function() {
            if(app.social_view == null) {
                app.social_view = new app.SocialView();
            }
        },
        instantiateContactUs: function() {
            if(app.contact_us_view == null) {
                app.contact_us_view = new app.ContactUsView();
            }

        },
        notFound: function() {
            if(app.not_found_view == null) {
                app.not_found_view = new app.NotFoundView();
            }

        }
    });

    app.router = new Router();

    var location_pathname = window.location.pathname;
    var site_url = location_pathname.replace(location_pathname.split("/").pop(),"");
    var urlArray = location_pathname.split("/");
    var pageUrl = urlArray[urlArray.length-1];
    if (Modernizr.history) {
        Backbone.history.start({pushState: true, root: site_url});
    } else {
        Backbone.history.start({hashChange: false, root: site_url});
    }

    app.router.navigate(pageUrl, {trigger: true});

})(jQuery);

修改

所以我已经知道按下后退按钮会触发路由器,而不必执行以下代码:

app.router.navigate(pageUrl, {trigger: true});

通常我在AJAX调用完成后运行上面的代码,所以我知道在实例化新视图之前所有元素都在页面上。

所以我想我现在的问题是:如何阻止后退按钮触发路由器?

修改

新路由器代码依赖于ajaxComplete()

instantiateOurWork: function() {
    if (app.ajaxActive) {
        $(document).ajaxComplete(function() {
            if(app.our_work_view == null) {
                app.our_work_view = new app.OurWorkView();
                $(document).unbind('ajaxComplete');
            }
        });
    } else {
        if(app.our_work_view == null) {
            app.our_work_view = new app.OurWorkView();
        }
        app.ajaxActive = true;
    }
},

这是非常混乱的代码,但我不知道如何做到这一点。

1 个答案:

答案 0 :(得分:0)

好的,所以我弄清楚了,这不是一个美丽的景象,但我不知道我还能怎么做。

首先,我需要确保在开始加载新视图之前所有ajax调用都已结束,这样可以防止任何时候存在多个视图并停止任何JS错误,这可以通过以下代码完成,这些代码也可以在我上面的一个编辑:

instantiateOurWork: function() {
    if (app.ajaxActive) {
        $(document).ajaxComplete(function() {
            if(app.our_work_view == null) {
                app.our_work_view = new app.OurWorkView();
                $(document).unbind('ajaxComplete');
            }
        });
    } else {
        if(app.our_work_view == null) {
            app.our_work_view = new app.OurWorkView();
        }
        app.ajaxActive = true;
    }
},

app.ajaxActive是一个全局变量,默认情况下设置为false,这是因为初始页面加载不执行AJAX调用,然后将其设置为true,这意味着它总是期望一个AJAX调用正在运行并等待它使用ajaxComplete函数完成。

我必须处理的下一个问题是终止在后台运行的代码,例如getScript()$.each循环会导致错误,因为他们会在查看后尝试运行除去。

要解决此问题,我必须实现默认情况下设置为this.stopExecution的本地变量false

调用我的this.removeView()函数时,this.stopExecution将设置为true

然后在删除视图后可能运行的任何代码中,我添加了以下代码:

if(self.stopExecution) {
    return false;
}

会阻止代码运行并防止出现任何错误。

如果有人有更好的解决方案,请随时分享。

感谢。