骨干.js 视图继承。父级中的“this”分辨率

Posted

技术标签:

【中文标题】骨干.js 视图继承。父级中的“this”分辨率【英文标题】:backbone.js view inheritance. `this` resolution in parent 【发布时间】:2011-06-06 20:04:50 【问题描述】:

我有一个使用视图继承的案例,我的代码看起来基本上是这样的:

parentView = Backbone.View.extend(
    events: 
        "some event": "business"
    ,
    initialize: function()
        _.bindAll(this);
    ,
    business: function(e)
        ...
        this.someFunc && this.someFunc();
        ...
     
);

childView = parentView.extend(
    events: 
        ...
    ,
    constructor: function()
       this.events = _.extend( , parentView.prototype.events, this.events );
       parentView.prototype.initialize.apply( this );
    ,
    initialize: function()
       _.bindAll(this);
    ,
    someFunc: function()
       ...
    
);

更新:将 this.events 扩展移至构造函数。

我的子视图中有someFunc,并且在父视图中的某些业务功能期间,如果该功能存在,它应该调用该功能。如果this 正确设置为childView,那么this.someFunc 应该存在。然而,这不是我正在经历的行为。

initialize 函数期间(在父视图中),this 确实设置为子视图。但是,当some event 触发时,将调用business 函数并将this 设置为parentView

【问题讨论】:

【参考方案1】:

您是否尝试过在构造函数中扩展this.events,而不是在初始化函数中?如果你在初始化时这样做,你就太晚了; business 函数的事件委托已在构造函数中设置,并将指向 parentView(参见 Backbone.View 的构造函数中对 this.delegateEvents(); 的调用)。

更新了一个工作示例:

ParentView = Backbone.View.extend(
    name: 'ParentView',
    events: 
        "event": "business"
    ,
    business: function(e)
        this.someFunc && this.someFunc();
    
);

ChildView = ParentView.extend(
    name: 'ChildView',
    events: 
    ,
    constructor: function()
       this.events = _.extend( , ParentView.prototype.events, this.events );
       console.debug( this.events );
       ParentView.prototype.constructor.apply( this, arguments );
    ,
    someFunc: function()
        console.debug('someFunc; this.name=%s', this.name);
    
);

child = new ChildView();
$( child.el ).trigger('event');
// logs 'this' in 'someFunc'; the name is 'ChildView'.

【讨论】:

好的,很酷。你能告诉我 parentView.prototype.initialize 和 parentView.constructor.initialize 的区别吗? 我更新了我的问题:同样的问题存在,即使使用这种技术。 parentView.constructor.initialize 未定义。 我也试过:parentView.prototype.constructor,没有任何运气。 更新了答案; parentView.constructor.initialize 是一个复制/粘贴错误,我的意思是 parentView.prototype.constructor 当然。为我工作! 不同的是先调用constructor,实际设置对象;通常,您不必触摸它。 constructor 然后继续设置事件,最后调用 initialize【参考方案2】:

实际上,我不知道这是否能解决您的问题,但我通常会这样做:this.constructor.__super__.initialize.apply(this, arguments); 并且效果很好。 我的解决方案完全错误。原因如下:

var Model1 = Backbone.Model.extend(
  method: function () 
    // does somehting cool with `this`
  
);

var Model2 = Model1.extend(
  method: function () 
    this.constructor.__super__.method.call(this);
  
);

var Model3 = Model2.extend(
  method: function () 
    this.constructor.__super__.method.call(this);
  
);

var tester = new Model3();

// Boom! Say hallo to my little stack-overflowing recursive __super__ call!
tester.method();

Model2::method 中对this.constructor.__super__ 的调用将解析为(鼓)Model2::method

总是使用ExplicitClassName.__super__.methodName.call(this, arg1, arg2 /*...*/)或Coffee-script的super

【讨论】:

我喜欢使用 super 而不是硬编码父类名【参考方案3】:

你可以通过在child的initialize方法中加入这一行来解决这个问题:

_.bind(this.business, this)

希望有人能给你指出比我能提供的更好的底层机制描述,但我会试一试:

除非另有说明,否则该方法将使用它定义的范围的上下文。当您调用 parentView.prototype.initialize.apply(this) 时,initialize 被告知使用子项的上下文,因为您通过对 apply 方法的 this 引用传入 childView。

您可以使用 underscore.js 的 bind 方法将业务方法绑定到孩子的上下文,如上所述。

【讨论】:

对,但这也是_.bindAll 函数的作用。通过在没有任何额外参数的情况下使用它,它应该绑定到对象中的所有函数。不幸的是,这也不起作用。

以上是关于骨干.js 视图继承。父级中的“this”分辨率的主要内容,如果未能解决你的问题,请参考以下文章

reactjs checkboxlist组件 - 更新父级中的状态更改

如何使用Vue从父级中的多个子组件中获取值?

其他 SQL 脚本执行的 SQL 脚本是不是继承父级中为所有客户端设置的系统变量?

父级中的Java方法占位符在子级中使用[重复]

在父级中反应handleClick

让 div 跟随光标在特定的 div 父级中