$(this.el)和这个。$ el在Backbone之间的区别

时间:2013-07-13 14:42:57

标签: backbone.js laravel

我正在使用Backbone和Laravel开发单页Web应用程序。我已将路由器设置为使用pushState并将Laravel配置为将所有其他请求发送到主干应用程序的主视图,其中主干负责路由。

我的问题/疑问如下:

我有一个名为'dashboard'的路线,这条路线是主应用程序视图,登录后显示。它使用名为Clients的集合。

dashboard:function(uri){
    dashboardCallback = function(data){
        if(data.check){
            console.log('generate dashboard');
            //get clients collection
            clientsCollection = new Dash.Collections.Clients();
            clientsCollection.fetch().then(function(clients){
                //genenerate dashboard view
                new Dash.Views.Dashboard({collection:clientsCollection}).renderDashboard();
            });
        }
        else{
            router.navigate('/', {trigger:true, replace:true});
        }
    }

    Dash.Utilities.user.isLoggedIn(dashboardCallback);
},

Dash.Views.Dashboard视图在调用renderDashboard()时处理应用程序中的所有视图;方法,它开始渲染所有客户端视图。这是它变得有趣的地方。

呈现所有客户端视图的代码如下:

renderClients:function(){
    console.log('Rendering all clients', this.collection);
    clientsView = new Dash.Views.Clients({collection:this.collection}).render();
    $(this.el).html(clientsView.el);
}

使用上面的代码,它适用于所有情况。我的意思是,当我首先登录并且应用程序将我路由到仪表板视图时,所有客户端都被呈现并附加到DOM,当我立即访问/dashboard时(同时应用程序检查我是否会发生)我登录了)。

但是,当我使用以下代码时,它在首次登录时不会加载客户端视图。当我直接访问/dashboard时,它会加载客户端视图。

renderClients:function(){
    console.log('Rendering all clients', this.collection);
    clientsView = new Dash.Views.Clients({collection:this.collection}).render();
    this.$el.html(clientsView.el);
}

我花了一段时间才弄清楚问题的解决方法是我必须用this.$el替换$(this.el),但我总是认为这无关紧要因为它们基本相同,或者我错了这个假设?

有人可以向我解释这种奇怪的行为吗?

根据要求,这是我的全局仪表板视图

Dash.Views.Dashboard = Backbone.View.extend({
    tagName:'div',

    id:'main',

    className:'dashboard',

    initialize: function(){
        console.log('Initializing Global Dashboard View');
        //make sure the main element is only added once.
        if(!$('.dashboard').length){
            $('body').append(this.el);
        }
        else{
            this.el = $('.dashboard');
        }
    },

    renderDashboard: function(){
        console.log('Render all Dashboard components');
        this.renderNavBar();
        this.renderClients();
    },

    renderNavBar: function(){
        var navBarView = new Dash.Views.NavBar().render();
        $(this.el).before(navBarView.el);
    },

    renderLogin: function(){
        var logInView = new Dash.Views.Login().render();
        $(this.el).html(logInView.el);
    },

    renderWhoops:function(error){
        console.log('Render Whoops from Global Dashboard');
        var whoopsModel = new Dash.Models.Whoops(error);
        $(this.el).html(new Dash.Views.Whoops({model:whoopsModel}).render().el)
    },

    renderClients:function(){
        console.log('Rendering all clients', this.collection);
        clientsView = new Dash.Views.Clients({collection:this.collection}).render();
        $(this.el).html(clientsView.el);
    }
});

1 个答案:

答案 0 :(得分:4)

我猜你的问题就在这里:

if(!$('.dashboard').length){
    $('body').append(this.el);
}
else{
    this.el = $('.dashboard');  // <----- Broken
}

如果没有.dashboard,则您直接分配给this.el,这是一个错误,因为它不会更新this.$el。结果是this.elthis.$el引用了不同的东西而没有任何作用。您应该使用setElement更改视图的el

  

setElement view.setElement(element)

     

如果您想将Backbone视图应用于其他DOM元素,请使用 setElement ,这也将创建缓存的$el引用并从旧视图移动视图的委派事件元素到新的。

所以你应该这样说:

if(!$('.dashboard').length){
    $('body').append(this.el);
}
else{
    this.setElement($('.dashboard')); // <----- Use setElement
}