gpt4 book ai didi

ajax - 仅将事件 ajaxStart() 和 ajaxStop() 附加到当前主干 View

转载 作者:行者123 更新时间:2023-11-30 23:58:30 27 4
gpt4 key购买 nike

我正在为我正在构建的应用程序使用主干。在这个应用程序中,我有一个主视图,它呈现一个模板,里面有 2 个其他 View 。一个标题 View 和另一个带有一些内容的 View 。标题 View 仅用于与内容 View 交互,也具有特定的功能。
在标题模板和内容模板中,我有相同的代码,一个隐藏的 DIV,带有一个加载器图像,在进行 ajax 调用时显示。我遇到的问题是,当我第一次加载应用程序时(或者当我刷新内容 View 时),内容 View 正在从 ajax 请求中加载一些数据,但是加载器同时显示在标题和内容中模板(例如如果 ajaxStart() 是未附加到 View 的全局事件。
这是内容 View 设置:

App.View.Content = Backbone.View.extend({
type:'test',
template: twig({
href: '/js/app/Template/Content.html.twig',
async: false
}),
block:{
test:twig({
href: '/js/app/Template/block/test.html.twig',
async: false
})
},
list:[],

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

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

initialize: function(params)
{
this.el = params.el;
this.type = params.type || this.type;
var self = this;

this.el
.ajaxStart(function(){self.showLoader(self.el);})
.ajaxStop(function(){self.hideLoader(self.el);});

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

refresh:function(page, limit)
{
var self = this;
console.log('Refreshing...');

$('#id-list-content').fadeOut('fast', function(){
$(this).html('');
});

this.list.type = this.type;
this.list.page = page || 1;
this.list.limit = limit || 10;

this.list.fetch({
success: function(data){
//console.log(data.toJSON());

$.each(data.toJSON(), function(){
//console.log(this.type);
var tpl_block = self.block[this.type];
if (tpl_block != undefined) {
var block = tpl_block.render({
test: this
});
$(block).appendTo('#id-list-content');
}
});

$('#id-list-content').fadeIn('fast');
}
});
},

render: function(callback)
{
console.log('Rendering list...');
this.el.html(this.template.render({

}));

if (undefined != callback) {
callback();
}
}
});

如您所见,我正在使用一段丑陋的代码来附加 ajaxStart/ajaxStop 事件:
this.el
.ajaxStart(function(){self.showLoader(self.el);})
.ajaxStop(function(){self.hideLoader(self.el);});
我以前是这样的:
this.el
.ajaxStart(self.showLoader())
.ajaxStop(self.hideLoader());
但无论出于何种原因,我仍然未定义, this.el未在 showLoader() 中定义和 hideLoader() .
我在想 ajaxStart()ajaxStop()已附加到 this.el DOM,并且只有这个 View 才能听到它。但是我的 headerView 具有完全相同的设置(加载的 Twig 模板除外)显然接收到事件并显示加载器。
为了确定这种行为,我注释掉了 showLoader()在内容 View 中,加载程序仍然显示在标题 View 中。
我不知道我做错了什么:(
编辑(在“亩太短”的回答后):
我的内容 View 现在看起来像这样:
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();
}
}
和我的标题 View :
...
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();
}
}
...
但是加载器仍然显示在标题 View 模板中
PS: this.showLoader()不是错字,因为我想在当前主干 View 中调用该函数。

最佳答案

JavaScript 函数的上下文(AKA this)取决于函数的调用方式,而不是定义函数的上下文。鉴于这样的事情:

var f = o.m;
f();

当您调用 o.m通过普通函数 f , this里面 o.m通常是全局上下文( window 在浏览器中)。您也可以使用 apply call 选择不同的 this所以这:
f.call(o);

会使 this o你会期望它是。我应该提一下,您可以强制选择 this使用 bind 在大多数 JavaScript 环境中,但我不想太过分心。

关键是:
this.el
.ajaxStart(this.showLoader)
.ajaxStop(this.hideLoader);

不足以确保 showLoaderhideLoader将在正确的上下文中运行;我还假设您在 showLoader 末尾的括号和 hideLoader只是错别字。

在 Backbone 应用程序中强制上下文的最常见方法是使用 _.bindAll 在您的 initialize :
initialize: function(params) {
_.bindAll(this, 'showLoader', 'hideLoader');
//...

这基本上取代了 this.showLoaderthis.hideLoader使用或多或少等同于您的包装器的东西:
function() { self.showLoader(self.el) }

一旦你有了 _.bindAll到位,这:
this.el
.ajaxStart(this.showLoader)
.ajaxStop(this.hideLoader);

会正常工作。

顺便说一句,你不需要这样做:
this.el = params.el;

在您的 initialize , Backbone does that for you :

constructor / initialize new View([options])

[...] There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName and attributes.



你不需要做这样的事情:
$('#ajax_loader', el).show();

或者,Backbone 会给你一个 $ method在您看来,在不隐藏 el 的情况下做同样的事情在参数列表的末尾;这样做:
this.$('#ajax_loader').show();

在 Backbone 中更惯用。

此外, this.el不一定是 jQuery 对象,所以不要这样做:
this.el.html(this.template.render({ ... }));

在您的 render , 使用缓存的 this.$el 反而:
this.$el.html(this.template.render({ ... }));

关于ajax - 仅将事件 ajaxStart() 和 ajaxStop() 附加到当前主干 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12138616/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com