编写在d3 ember组件中调用其他方法的方法?

时间:2013-10-27 06:32:25

标签: ember.js d3.js

假设我在Ember中创建了一个可重用的组件,我想要一个调用其中定义的另一个辅助函数的辅助函数。例如,

App.SomeCoolComponent = Ember.Component.extend

  offset: 50

  position: (x) -> x * 100

  offsetPosition: # would like (x) -> position(x) + offset

从概念上讲,返回一个函数来评估x处的位置,添加偏移量和返回值。显然这是一个愚蠢的例子,我可以在不调用offSetPosition的情况下编写position,但是在更复杂的情况下重复代码。问题是我无法弄清楚如何让它工作。我试过了

  offsetPosition: (x) -> @get('position')(x) + @get('offset')

失败,因为@get未在函数中定义,它的范围错误。我试图在不同的地方插入像Ember.computed这样的东西,但没有运气,例如以下也不起作用:

  offsetPosition: Ember.computed(->
    (x) -> @get('position')(x) + @get('offset')).property('position', 'offset')

这样做的正确方法是什么?

Ember版本1.3.0-beta.1 + canary.48513b24。提前谢谢!

编辑:好像我的问题源于将函数传递给d3调用。例如:

App.SomeCoolComponent = Ember.Component.extend

  offset: 50

  position: (d, i) -> i * 100

  offsetPosition: (d, i) ->
    @position(d, i) + @get('offset')

  # Some other code not shown

  didInsertElement: ->
    data = [1, 2, 3]
    i = 1
    d = data[i]
    console.log(@position(d, i)) # works
    console.log(@offsetPosition(d, i)) # works

    d3.select('svg').selectAll('circle').data(data).enter().append('circle')
      .attr('cx', @position) # works
      .attr('cy', @offsetPosition) # fails
      .attr('r', 30)

错误讯息为Uncaught TypeError: Object #<SVGCircleElement> has no method 'position'

有关如何解决此问题的任何想法?

2 个答案:

答案 0 :(得分:1)

方法(又名不是计算属性)在当前上下文中,应该像方法一样调用,而不是使用getter / setter。

offsetPosition:(x) - &gt;   @position(x)+ @get(&#34; offset&#34;)

位置:(x) - &gt;   x * 100

以下是一个例子:http://emberjs.jsbin.com/eWIYICu/3/edit

App.AnAppleComponent = Ember.Component.extend({
  offset: 50,

  position: function(x) {
    return x * 100;
  },

  offsetPosition: function(x) {
    return this.position(x) + this.get('offset');
  },

  displayOffset: function(){
    return this.offsetPosition(Math.floor(Math.random() * 10) + 1);
  }.property('offset')

});

我个人创建一个mixin并在那里添加我的方法,然后在需要逻辑的地方添加mixin。 Mixins属于添加它们的范围。

BTW您可以在应用中的任何位置使用Ember.Get(对象,&#39; propertyOnObject&#39;)。

为了响应您的编辑,您将方法传入这些属性值而不是这些方法的值(这就是为什么它在上面工作,但不在下面)。很有可能因为你发送这些方法,jquery后来将这些方法应用到范围之外。

didInsertElement: ->
  data = [1, 2, 3]
  i = 1
  d = data[i]
  position = @position(d, i)
  offsetPosition = @offsetPosition(d, i)
  console.log position
  console.log offsetPosition
  d3.select("svg").selectAll("circle").data(data).enter().append("circle").attr("cx", position).attr("cy", offsetPosition).attr "r", 30

我有一种感觉,你想要动态更新或沿着那些方向的东西,如果你真的想要使用计算属性,Ember的培根。这是苹果组件的更新版本:

http://emberjs.jsbin.com/eWIYICu/5/edit

<div {{bind-attr style='dynamicStyle'}}>

dynamicStyle: function(){
  var rgb = this.get('rgb'),
      rgb1 = rgb * 21 % 255,
      rgb2 = rgb * 32 % 255,
      rgb3 = rgb * 41 % 255;
  return 'background-color:rgb(' + rgb1 + ',' + rgb2 + ',' + rgb3 + ');';
}.property('rgb'),

答案 1 :(得分:1)

问题是您正在将函数offsetPosition(引用this并希望它指向App.SomeCoolComponent)传递给D3回调,其中this被替换为DOMElement d3.select('svg').selectAll('circle').data(data).enter().append('circle') .attr('cx', @position) # works .attr('cy', (d, i) => @offsetPosition(d, i)) .attr('r', 30)

您可以通过两种方式解决问题:

  1. 使用fat arrow syntax

    bind
  2. 明确使用d3.select('svg').selectAll('circle').data(data).enter().append('circle') .attr('cx', @position) # works .attr('cy', @offsetPosition.bind(this)) .attr('r', 30)

    {{1}}