函数_.bind()不会绑定对象

时间:2021-08-11 19:36:20

I have a view class extending SugarCRM CreateView and I want this to be this.model in function checkMonths when the field starting_months_c is changed, so I could type this.get() instead of this.model.get().

我有一个扩展SugarCRM CreateView的视图类,我希望在更改字段starting_months_c时函数checkMonth中的this.model,所以我可以输入this.get()而不是this.model.get()。

/**
 * @class View.Views.Base.DoVPCreateView
 * @alias SUGAR.App.view.views.DoVPCreateView
 * @extends View.Views.Base.CreateView
 */
({
    extendsFrom: 'CreateView',
    initialize: function(options) {
        this._super('initialize', arguments);
        // ....
        this.model.on('change:starting_month_c', _.bind(this.checkMonths, this.model));
        // ....
    },
    checkMonths: function() {
        if (this.get('starting_month') == 12) {
            // ....
        }
    }

Unfortunately, this construct does not work. I wonder, maybe it is because the .on() function somehow sets the context itself?

不幸的是,这种结构不起作用。我想知道,也许是因为.on()函数以某种方式设置了上下文本身?

I found out in the doc, that you can pass the context to the function as third parameter

我在文档中发现,您可以将上下文作为第三个参数传递给函数

object.on(event, callback, [context])

I tried this but the result is still the same - the view is this, not the model.

我试过这个,但结果仍然是相同的 - 视图是这个,而不是模型。

2 个解决方案

#1


2  

Quick fix

Give the context directly to .on:

直接将上下文提供给.on:

this.model.on('change:starting_month_c', this.checkMonths, this.model);

But doing this is only a misleading fix. The view's functions should all have this being the view instance and not other arbitrary objects.

但这样做只是一个误导性的解决方案。视图的函数应该都是视图实例,而不是其他任意对象。

// a simple example view
var View = Backbone.View.extend({
  initialize: function() {
    console.log("View init, month:", this.model.get('month'));
    
    // bind the context
    this.model.listenTo(this.model, "change:month", this.checkMonth);
  },
  // the callback
  checkMonth: function() {
    // here, `this` is the model which you should NOT do.
    // but for demonstration purpose, you can use `this.get` directly.
    console.log("checkMonth:", this.get('month'));
  },
});

// sample for the demo
var model = new Backbone.Model({
    month: 2 // dummy value
  }),
  view = new View({
    model: model
  });

console.log("change month");
model.set({
  month: 3 // set to trigger the callback
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

Real fix

If you always want to trigger a check "months" callback whenever starting_month_c changes in any instance of this model, you could move that into the model class itself.

如果您始终想要在此模型的任何实例中的starting_month_c更改时触发检查“months”回调,则可以将其移动到模型类本身。

var Model = Backbone.Model.extend({
    initialize: function() {
        // favor listenTo over `on` or `bind`
        this.listenTo(this, 'change:starting_month_c', this.checkMonths);
    },
    checkMonths: function(model, value, options) {
        if (this.get('starting_month') === 12) {
            // whatever you want
        }
    }
});

If it's only for this specific view, use this.model.get in the callback as it should be. This is not a problem, it's the standard way of doing it.

如果它仅适用于此特定视图,请在回调中使用this.model.get。这不是问题,这是标准的做法。

More info on why to favor listenTo.

关于为什么喜欢listenTo的更多信息。

#2


0  

Maybe the context is more this than this.model:

也许上下文比this.model更多:

.bind(this.checkMonths, this)

http://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_7.8/User_Interface/Views/Adding_Field_Validation_to_the_Record_View/index.html

#1


2  

Quick fix

Give the context directly to .on:

直接将上下文提供给.on:

this.model.on('change:starting_month_c', this.checkMonths, this.model);

But doing this is only a misleading fix. The view's functions should all have this being the view instance and not other arbitrary objects.

但这样做只是一个误导性的解决方案。视图的函数应该都是视图实例,而不是其他任意对象。

// a simple example view
var View = Backbone.View.extend({
  initialize: function() {
    console.log("View init, month:", this.model.get('month'));
    
    // bind the context
    this.model.listenTo(this.model, "change:month", this.checkMonth);
  },
  // the callback
  checkMonth: function() {
    // here, `this` is the model which you should NOT do.
    // but for demonstration purpose, you can use `this.get` directly.
    console.log("checkMonth:", this.get('month'));
  },
});

// sample for the demo
var model = new Backbone.Model({
    month: 2 // dummy value
  }),
  view = new View({
    model: model
  });

console.log("change month");
model.set({
  month: 3 // set to trigger the callback
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

Real fix

If you always want to trigger a check "months" callback whenever starting_month_c changes in any instance of this model, you could move that into the model class itself.

如果您始终想要在此模型的任何实例中的starting_month_c更改时触发检查“months”回调,则可以将其移动到模型类本身。

var Model = Backbone.Model.extend({
    initialize: function() {
        // favor listenTo over `on` or `bind`
        this.listenTo(this, 'change:starting_month_c', this.checkMonths);
    },
    checkMonths: function(model, value, options) {
        if (this.get('starting_month') === 12) {
            // whatever you want
        }
    }
});

If it's only for this specific view, use this.model.get in the callback as it should be. This is not a problem, it's the standard way of doing it.

如果它仅适用于此特定视图,请在回调中使用this.model.get。这不是问题,这是标准的做法。

More info on why to favor listenTo.

关于为什么喜欢listenTo的更多信息。

#2


0  

Maybe the context is more this than this.model:

也许上下文比this.model更多:

.bind(this.checkMonths, this)

http://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_7.8/User_Interface/Views/Adding_Field_Validation_to_the_Record_View/index.html