【问题标题】:Is it possible to bind a parent component’s property, via template, to a child component computed property?是否可以通过模板将父组件的属性绑定到子组件的计算属性?
【发布时间】:2015-02-17 14:01:03
【问题描述】:

是否可以通过模板将父组件的属性绑定到子组件的计算属性?

目标是通过绑定访问子组件的计算属性。

// We are in some parent component's template
{{child-component aComputedProp=aNonComputedProp}}

// Parent component
export default Ember.Component.extend({
  aNonComputedProp: null
});

// Child component
export default Ember.Component.extend({
  aComputedProp: function () {
    return 4 + 4;
  }.property()
});

更新

@KalmanKalman Hazins

虽然这种方法在对该子组件执行操作时效果很好,但当祖先组件需要访问该子组件的数据时,它就不起作用了。

这是描述困境的图片。

我能想到的让组件相互通信而没有硬依赖的唯一方法是通过服务(或充当服务的父组件)和一系列伪装成 API 的触发器/处理程序事件.

更新

我正在考虑的另一种方法是通过以下方式从 ChildComponent1 装饰父控制器:

  decorateTargetObject: function () {
    Ember.defineProperty(this.get('targetObject'), 'height', Ember.computed(function () {
      return this.$().outerHeight();
    }.bind(this)));
  }.on('init')

并且 ChildComponent2 可以通过 this.get('targetObject.height') 访问该属性

由于组件需要插入其控制器,因此这会破坏单向封装。

有没有办法将现有属性设置为计算属性而不重新定义它(没有Ember.defineProperty)?

//In ChildComponent1
decorateTargetObject: function () {
  this.set('targetObject.height', ...a computed function...)
}.on('init')

【问题讨论】:

    标签: ember.js


    【解决方案1】:

    这是不可能的(直接通过模板),但你会这样做:)(相反)。

    您可以向父级发送一个操作并将其传递给要更改的值。然后,在父操作中,您可以更新该值。

    App.XParentComponent = Ember.Component.extend({
      helloParent: null,
    
      actions: {
        updateHelloParent: function(value){
          this.set('helloParent', value);
        }
      }
    });
    
    App.XChildComponent = Ember.Component.extend({
      helloName: function(){
        var name = this.get('name');
        var helloName = '';
        if(name) {
          var helloName = "Hello " + name;
        }
    
        this.sendAction('action', helloName);
    
        return helloName;      
      }.property('name')
    });
    

    您的模板如下所示:

    <script type="text/x-handlebars" id="components/x-parent">
      <h2>Parent</h2>
    
      {{ helloParent }}
    
      {{ x-child action="updateHelloParent"}}
    </script>
    
    <script type="text/x-handlebars" id="components/x-child">
      <h2>Child</h2>
    
      {{ input value=name }} <p/> 
    
      {{ helloName }}
    </script>
    

    工作解决方案here

    更新

    基于docs,您可以针对您的用例执行以下操作:

    App.HeightController = Ember.Controller.extend({
      height: 0
    });
    
    App.IndexController = Ember.Controller.extend({
      needs: ['height'],
      height: Ember.computed.alias('controllers.height.height')
    });
    
    App.XChild1Component = Ember.Component.extend({
      heightDidChange: function(){
        var val = this.get('val');
        if(val) {
          this.set('height', parseInt(val));  
        }    
      }.observes('val')
    });
    

    然后,在您的模板中,您可以拥有以下内容:

    <script type="text/x-handlebars" data-template-name="index">
      Height(index): {{ height }} <p/>
      {{ x-parent height=height}}
    </script>
    
    <script type="text/x-handlebars" id="components/x-parent">
      <h2>Parent</h2>
    
      Height(parent): {{ height }} <p/>
    
      {{ x-child1 height=height}}
    
      {{ x-child2 height=height}}
    </script>
    
    <script type="text/x-handlebars" id="components/x-child1">
      <h2>Child 1</h2>
    
      Height(child1): {{ height }} <p/>
      {{ input value=val placeholder='Type new heght here...'}} <p/> 
    
    </script>
    
    <script type="text/x-handlebars" id="components/x-child2">
      <h2>Child 2</h2>
    
      Height(child2): {{ height }} <p/>    
    </script>
    

    更新解决方案here

    【讨论】:

    • 这个方法的2个问题:[1]如果属性不能被观察到怎么办,例如jQuery的outerWidth方法,因此它需要是一个计算属性。 [2] 由于组件使用observes,所以被观察的属性需要触发一个更改事件,如果它永远不会改变呢?
    猜你喜欢
    • 2020-09-30
    • 2018-02-13
    • 2011-04-01
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    相关资源
    最近更新 更多