从嵌套d3函数中引用主干函数

时间:2013-05-21 14:43:48

标签: javascript backbone.js d3.js

我试图在骨干render函数内的d3函数中引用骨干函数。我现在必须引用其他Backbone函数,做一些backboney的东西,但不能通过使用this / that方法引用它来访问它们(我用这个/ƒthis):

define([
  // this is for require.js file modularization 
], function(){
  return Backbone.View.extend({
    initialize: function(options){
      //CODE
      this.render();
    },

    render: function(options){
      // HOW I ACCESS THE BACKBONE VIEW IN NESTED SITUATIONS
      var ƒthis = this;    

      //NORMAL RENDERING
      if (!options) {        
        // Do some stuff, get some vars

        // compile the template

        // D3 stuff
        var lineData = ({...});
        var pathFunction = d3.svg.line()
        var beatUnwindingPaths = [......];

        var beatContainer = d3.select('#beatHolder'+this.parent.cid);
        var beatPath = beatContainer //.append('g')
            .insert('path', ':first-child')
            .data([beatUnwindingPaths[0]])
            .attr('d', pathFunction)
            .attr('class', 'beat')
   //THIS IS WHERE I WANT TO REFERENCE THE FUNCTION TO BE CALLED, AND HOW I THINK IT SHOULD BE CALLED
            .on('click', ƒthis.toggle);
   //BUT CURRENTLY I AM ONLY LIMITED TO CALLING A FUNCTION DECLARED WITHIN THE BACKBONE render func(), so it would look like this:
            .on('click', toggle);

   //CURRENTLY I AM HAVING TO DECLARE THE FUNCTIONS INSIDE RENDER
        function unroll() {
          //do some stuff
        };
        function reverse() {
        };
        $('#a').on('click', unroll);
        $('#b').on('click', reverse);
      }
    },

// THIS IS THE FUNCTION I WANT TO CALL
    toggle: function(){
       //DO some stuff to the other BackBone models, collections and other cool stuff
    }
  });
});

如何从D3代码中访问Backbone toggle函数?

错误代码来自toggle函数本身(以前工作过,所以我试图找出它为什么不是现在),并且错误是313,而不是314,我的浏览器控制台总是一行关闭。我把一个console.log()看成是用函数中的ƒthis.toggle看到的,但是在切换bool值时出错了。

311 toggle: function(){
312   //switch the selected boolean value on the model
313   this.model.set('selected', !this.model.get('selected'));
314   //re-render it, passing the clicked beat to render()
315   this.render(this.model);
316   // log.sendLog([[1, "beat" + this.model.cid + " toggled: "+!bool]]);
317   dispatch.trigger('beatClicked.event');
318 }

我从渲染模板中的圆圈切换到让d3创建它(因此我们可以使用d3函数对其进行动画处理),我认为对象已经失去了对模型的绑定。正在努力......

1 个答案:

答案 0 :(得分:2)

这不是D3 / Backbone问题,它只是Javascript。您不能传递稍后要调用的对象方法,并期望this在该方法中工作,除非您以某种方式绑定它:

var myObject = {
    method: function() {
        this.doSomeStuff();
    },
    doSomeStuff: function() {
        console.log("stuff!");
    }
};

myObject.method(); // "stuff!"

// pass this method somewhere else - this is
// effectively what you do with an event handler
var myMethod = myObject.method;

myMethod(); // TypeError: Object [object global] has no method 'doSomeStuff'

第二部分失败,因为调用myObject.myMethod()this绑定到myObject,但是将方法分配给变量(或将其指定为事件处理程序)则不会(在大多数情况下) ,this绑定到window,但D3会将this重新分配给您设置处理程序的DOM元素。

标准修正是1)将其包装在一个函数中:

var myMethod = function() {
    myObject.method();
};

myMethod();  // "stuff!"

或2)以某种方式将其绑定到对象,例如在你的Backbone initialize方法中(Underscore为此目的提供了一个有用的_.bindAll实用程序):

Backbone.View.extend({
    initialize: function(options){
        _.bindAll(this, 'toggle');
        // now you can pass this.toggle around with impunity
    },
    // ...
});