仅将事件ajaxStart()和ajaxStop()附加到当前主干视图

仅将事件ajaxStart()和ajaxStop()附加到当前主干视图,ajax,backbone.js,backbone-views,Ajax,Backbone.js,Backbone Views,我正在为我正在构建的应用程序使用主干网。在这个应用程序中,我有一个主视图,它可以呈现一个模板,其中包含两个其他视图。一个标题视图和另一个包含某些内容的视图。header视图仅用于与content视图交互,并具有特定的功能 在header模板和content模板中,我有相同的代码,一个隐藏的DIV,带有一个加载程序图像,在进行ajax调用时显示该图像。我遇到的问题是,当我第一次加载应用程序时(或者当我刷新内容视图时),内容视图正在从ajax请求加载一些数据,但加载程序同时显示在标题和内容模板中(就

我正在为我正在构建的应用程序使用主干网。在这个应用程序中,我有一个主视图,它可以呈现一个模板,其中包含两个其他视图。一个标题视图和另一个包含某些内容的视图。header视图仅用于与content视图交互,并具有特定的功能

在header模板和content模板中,我有相同的代码,一个隐藏的DIV,带有一个加载程序图像,在进行ajax调用时显示该图像。我遇到的问题是,当我第一次加载应用程序时(或者当我刷新内容视图时),内容视图正在从ajax请求加载一些数据,但加载程序同时显示在标题和内容模板中(就像ajaxStart()是未附加到视图的全局事件一样)

以下是内容视图设置:

如您所见,我正在使用一段难看的代码来附加ajaxStart/ajaxStop事件:

this.el
    .ajaxStart(function(){self.showLoader(self.el);})
    .ajaxStop(function(){self.hideLoader(self.el);});
我过去经常这样做:

this.el
    .ajaxStart(self.showLoader())
    .ajaxStop(self.hideLoader());
showLoader: function(){
            //this.$('#ajax_loader').show();
            console.log('Ajax request started...');
        },

        hideLoader: function(){
            this.$('#ajax_loader').hide();
            console.log('Ajax request ended...');
        },

        initialize: function(params)
        {
            var self  = this;

            console.log(this.el);

            _.bindAll(this, 'showLoader', 'hideLoader');

            this.$el
                .ajaxStart(this.showLoader)
                .ajaxStop(this.hideLoader);

            this.render(function(){
                self.list = new App.Collection.List();
                self.refresh(1, 10);
            });
        },
...

render: function(callback)
        {
            console.log('Rendering post by page...');
            this.$el.html(this.template.render({

            }));

            if (undefined != callback) {
                callback();
            }
}
var f = o.m;
f();
$('#ajax_loader', el).show();
this.$('#ajax_loader').show();
但是,无论出于什么原因,我仍然没有定义,
this.el
没有在
showLoader()
hideLoader()
中定义

我认为
ajaxStart()
ajaxStop()
被附加到
this.el
DOM,并且只有这个视图能够侦听它。但是我的headerView具有完全相同的设置(除了加载的细枝模板),它显然接收到事件并显示加载程序

为了确保这种行为,我在内容视图中注释掉了
showLoader()
,加载程序仍然显示在标题视图中

我不知道我做错了什么:(

编辑(在“mu太短”的回答之后):

“我的内容”视图现在看起来如下所示:

this.el
    .ajaxStart(self.showLoader())
    .ajaxStop(self.hideLoader());
showLoader: function(){
            //this.$('#ajax_loader').show();
            console.log('Ajax request started...');
        },

        hideLoader: function(){
            this.$('#ajax_loader').hide();
            console.log('Ajax request ended...');
        },

        initialize: function(params)
        {
            var self  = this;

            console.log(this.el);

            _.bindAll(this, 'showLoader', 'hideLoader');

            this.$el
                .ajaxStart(this.showLoader)
                .ajaxStop(this.hideLoader);

            this.render(function(){
                self.list = new App.Collection.List();
                self.refresh(1, 10);
            });
        },
...

render: function(callback)
        {
            console.log('Rendering post by page...');
            this.$el.html(this.template.render({

            }));

            if (undefined != callback) {
                callback();
            }
}
var f = o.m;
f();
$('#ajax_loader', el).show();
this.$('#ajax_loader').show();
和我的标题视图:

...
showLoader: function(){
            this.$('#ajax_loader').show();
            //console.log('Ajax request started...');
        },

        hideLoader: function(el){
            this.$('#ajax_loader').hide();
            console.log('Ajax request ended...');
        },

        initialize: function(params)
        {
            var self = this;
            _.bindAll(this, 'showLoader', 'hideLoader');

            this.$el
                .ajaxStart(this.showLoader)
                .ajaxStop(this.hideLoader);

            this.models.Link = new App.Model.Link();
            this.render();
        },

        render: function(callback)
        {
            this.$el.html(this.template.render({
                data: []
            }));

            if (undefined != callback) {
                callback();
            }
        }
...
但是加载程序仍然显示在标题视图模板中

PS:
this.showLoader()
不是一个打字错误,因为我想在当前主干视图中调用函数。

JavaScript函数的上下文(也称为
this
)取决于函数的调用方式,而不是函数定义的上下文。考虑到以下情况:

this.el
    .ajaxStart(self.showLoader())
    .ajaxStop(self.hideLoader());
showLoader: function(){
            //this.$('#ajax_loader').show();
            console.log('Ajax request started...');
        },

        hideLoader: function(){
            this.$('#ajax_loader').hide();
            console.log('Ajax request ended...');
        },

        initialize: function(params)
        {
            var self  = this;

            console.log(this.el);

            _.bindAll(this, 'showLoader', 'hideLoader');

            this.$el
                .ajaxStart(this.showLoader)
                .ajaxStop(this.hideLoader);

            this.render(function(){
                self.list = new App.Collection.List();
                self.refresh(1, 10);
            });
        },
...

render: function(callback)
        {
            console.log('Rendering post by page...');
            this.$el.html(this.template.render({

            }));

            if (undefined != callback) {
                callback();
            }
}
var f = o.m;
f();
$('#ajax_loader', el).show();
this.$('#ajax_loader').show();
当您通过普通函数
f
调用
o.m
时,
o.m
中的
通常是全局上下文(
浏览器中的窗口
)。您还可以使用和选择不同的
,因此:

f.call(o);
会使
这个
成为你所期望的
o
。我应该提到的是,在大多数JavaScript环境中,你可以强制选择
这个
,但我不想太离题

关键是:

this.el
    .ajaxStart(this.showLoader)
    .ajaxStop(this.hideLoader);
不足以确保
showLoader
hideLoader
将在正确的上下文中运行;我还假设您在
showLoader
hideLoader
末尾的括号只是打字错误

在主干应用程序中强制上下文的最常见方法是在
初始化中使用:

initialize: function(params) {
    _.bindAll(this, 'showLoader', 'hideLoader');
    //...
基本上,它将
this.showLoader
this.hideLoader
替换为与包装器大致相同的内容:

function() { self.showLoader(self.el) }
.bindAll
放置到位后,将:

this.el
    .ajaxStart(this.showLoader)
    .ajaxStop(this.hideLoader);
会很好的


顺便说一句,你不需要这样做:

this.el = params.el;
初始化
中,主干:

构造函数/初始化
新视图([options])

[…]有几个特殊选项,如果通过,将直接附加到视图:
模型
集合
el
id
类名
标记名
属性

你不需要这样做:

this.el
    .ajaxStart(self.showLoader())
    .ajaxStop(self.hideLoader());
showLoader: function(){
            //this.$('#ajax_loader').show();
            console.log('Ajax request started...');
        },

        hideLoader: function(){
            this.$('#ajax_loader').hide();
            console.log('Ajax request ended...');
        },

        initialize: function(params)
        {
            var self  = this;

            console.log(this.el);

            _.bindAll(this, 'showLoader', 'hideLoader');

            this.$el
                .ajaxStart(this.showLoader)
                .ajaxStop(this.hideLoader);

            this.render(function(){
                self.list = new App.Collection.List();
                self.refresh(1, 10);
            });
        },
...

render: function(callback)
        {
            console.log('Rendering post by page...');
            this.$el.html(this.template.render({

            }));

            if (undefined != callback) {
                callback();
            }
}
var f = o.m;
f();
$('#ajax_loader', el).show();
this.$('#ajax_loader').show();
或者,主干在视图中为您提供了一个相同的操作,而不隐藏参数列表末尾的
el
;这样做:

this.el
    .ajaxStart(self.showLoader())
    .ajaxStop(self.hideLoader());
showLoader: function(){
            //this.$('#ajax_loader').show();
            console.log('Ajax request started...');
        },

        hideLoader: function(){
            this.$('#ajax_loader').hide();
            console.log('Ajax request ended...');
        },

        initialize: function(params)
        {
            var self  = this;

            console.log(this.el);

            _.bindAll(this, 'showLoader', 'hideLoader');

            this.$el
                .ajaxStart(this.showLoader)
                .ajaxStop(this.hideLoader);

            this.render(function(){
                self.list = new App.Collection.List();
                self.refresh(1, 10);
            });
        },
...

render: function(callback)
        {
            console.log('Rendering post by page...');
            this.$el.html(this.template.render({

            }));

            if (undefined != callback) {
                callback();
            }
}
var f = o.m;
f();
$('#ajax_loader', el).show();
this.$('#ajax_loader').show();
在主干方面更为惯用

此外,
this.el
不一定是jQuery对象,所以不要这样做:

this.el.html(this.template.render({ ... }));
渲染中
,使用缓存的:


感谢您宝贵的回复,但是加载程序仍然显示在标题模板中:(从我在文档中可以看到()
ajaxStart()
是一个全局事件。每次有ajax请求时都会触发它。您不能执行
$(DOM).ajaxStart(function(){console.log('triggered'));
并期望DOM元素触发ajax请求。我说得对吗?我的问题有什么解决方案:(?@maxwell2022:right,
$(x)。ajaxStart()
是个谎言,因为它真正的意思是
$(任何东西)。ajaxStart()
。您必须通过
$.AJAX
参数或通过返回的
jqXHR
绑定到所需的特定AJAX调用。因为当我获取它时,正是集合神奇地触发了AJAX调用,所以我不能将其与$.AJAX绑定,可以吗?另外,如果每个视图有20个AJAX调用,我只想触发一个我绑定到视图中以显示同一加载程序的事件。集合具有您可能可以使用的成功和错误回调。如果要添加“开始提取”,您还可以提供自己的
sync
fetch
方法事件。我通常在执行
fetch
之前放置加载程序,然后在
fetch
完成获取后调用
render
时,加载程序就会离开。