Javascript 不会重新计算基于数组值的计算属性 问题空间

Javascript 不会重新计算基于数组值的计算属性 问题空间,javascript,coffeescript,ember.js,Javascript,Coffeescript,Ember.js,我正在渲染一些嵌套的余烬视图,以便创建拆分器窗格样式的UI。我想在第一次渲染视图时调整视图的大小,以便它们具有相同的宽度。我不希望我的子视图彼此对视,因此我使用Ember.ContainerView的子类来保存我的内容和可拖动的拆分器句柄 我不能在容器视图上使用Ember.View#didinserelement,因为我需要等待子视图完全呈现 我的(尝试的)解决方案 我正在使用此答案中提供的代码:。这将向所有Ember.View实例添加属性isRendered,该属性在模板通过重新打开Ember

我正在渲染一些嵌套的余烬视图,以便创建拆分器窗格样式的UI。我想在第一次渲染视图时调整视图的大小,以便它们具有相同的宽度。我不希望我的子视图彼此对视,因此我使用
Ember.ContainerView
的子类来保存我的内容和可拖动的拆分器句柄

我不能在容器视图上使用
Ember.View#didinserelement
,因为我需要等待子视图完全呈现

我的(尝试的)解决方案 我正在使用此答案中提供的代码:。这将向所有
Ember.View
实例添加属性
isRendered
,该属性在模板通过重新打开Ember触发
didInsertElement
时自动设置。视图:

Ember.View.reopen

  didInsertElement: ->
    res = @_super();
    @_setIsRendered();
    res

  _setIsRendered: ->
    if (!! @$())
      @set('isRendered', true)
    else
      Ember.run.next this, ->
        @_setIsRendered()
我尝试重新打开
Ember.ContainerView
以向所有容器视图添加
childViewsRendered
属性,但Ember反对,并对childViews中只有一项的容器视图抛出了一些非常奇怪的IndexOutOfBounds错误

我最终将我的收藏代码放在以下mixin中:

App.ChildrenRendered = Ember.Mixin.create

  childViewsRendered: (->
    res = @get('childViews').everyProperty('isRendered')
    console.log('childViewsRendered', res, this)

    # Pointer to this most offensive object for debugging
    window.wtf = this
    res
  ).property('childViews.@each.isRendered')

  _runChildViewsDidRender: (->
    if @get('childViewsRendered')
      console.log('trying to invoke childViewsDidRender')
      Ember.tryInvoke(this, 'childViewsDidRender')
  ).observes('childViewsRendered')
然后我有一节课是这样的:

App.SplitterView = Ember.ContainerView.extend App.ChildrenRendered,
  # ...(some properties)...
  init: ->
    child_views = @get('childViews')
    child_views.pushObjects([App.WindowView.create(), App.WindowView.create()])

工作原理:
  • App.SplitterView#childViewsRendered
    在任何视图渲染之前计算一次,因此变为
    false
  • 视图由Ember处理(插入和渲染),并设置其自己的
    isRendered
    属性fine and dandy
  • 稍后运行
    window.wtf.get('childview')。everyProperty('isRendered')
    返回
    true
什么不起作用:
  • 计算属性
    childViewsRendered
    不再更新自身
  • childView
    数组元素成员上的虚拟值的计算属性似乎也不起作用

    • 如果没有jsFiddle,我只能看你说的话和你提供的代码片段,但似乎你所要做的就是确保容器的所有子视图都在DOM中,然后再执行操作,是吗

      如果是这样的话。。。当视图添加到
      childview
      时,您知道,它们会自动呈现并插入到DOM中。这一切都发生在同一个运行循环中。因此,要将某些函数的执行延迟到所有子函数都是“inDOM”,只需观察
      childview.@each
      并使用
      Ember.run.next
      将执行延迟到下一个RunLoop即可。这里有一个例子

      App.SomeContainerView = Em.ContainerView.extend
        init: ->
          @_super() # run default init
          # add 2 of our 4 views
          @get('childViews').pushObjects [@aView.create(), @bView.create()]
      
        # a non-cached (volatile) computed property to check if children are inDOM
        # just used for demo purposes
        childrenAreInDom: (->
          @get('childViews').every (v) ->
            v.state is "inDOM"
        ).property().volatile()
      
        # our observer
        observeChildren: (->
          # if the container isn't inDOM yet the afterRender function we add below 
          # will handle it, if views are added/removed after that then we handle it here
          return unless @state is "inDOM"
          # output to console if every childview are inDOM
          console.log "observeChildren", @get('childrenAreInDom')
          # the above will always be false since we're still in the same RunLoop
          # next RunLoop our function will run
          Ember.run.next @, 'doWhatever'
        ).observes('childViews.@each') # observe changes in the childViews array
      
        afterRender: ->
          console.log "afterRender", @get('childrenAreInDom')
          Ember.run.next @, 'doWhatever'
      
        # the function we want to run eventually after children are inDOM
        doWhatever: ->
          console.log "doWhatever"
          # print out childrenAreInDom one more time.. it will be true
          console.log "childrenAreInDom:", @get('childrenAreInDom')
      
        # some views to insert
        aView: Em.View.extend
          template: Em.Handlebars.compile("A")
        bView: Em.View.extend
          template: Em.Handlebars.compile("B")
        cView: Em.View.extend
          template: Em.Handlebars.compile("C")
        dView: Em.View.extend
          template: Em.Handlebars.compile("D")
      
      如果模板中有{{view App.SomeContainerView}},在控制台中您会看到:

      afterRender false
      doWhatever
      childrenAreInDom true 
      
      如果在容器已经在DOM中之后,通过pushObjects以编程方式添加cView和dView,您将看到

      observeChildren false
      doWhatever
      childrenAreInDom true 
      
      即使这不完全是你想要的,希望它能帮助你达到你需要的地方,而不需要那些混搭的废话:D