EmberJS关于控制器,服务和组件使用的建议

时间:2016-06-17 08:43:27

标签: javascript ember.js

我正在试图弄清楚如何正确处理控制器和几个组件之间的通信。我想我需要在这里使用一项服务,但也许另一种解决方案更合适。

这个想法是,用户可以获得一个问题的课程。当用户单击检查按钮时,应该向后端API发出请求以检查答案是否正确。棘手的部分是问题可以有不同的类型:开放式问题,多项选择和拖放。

有一个/lesson/template.hbs,总结如下:

customizable behavior

然后,我的想法是有一个lesson / controller.js来处理nextQuestion和checkAnswer点击动作:

ProcessOrder

要有一个负责粘合控制器和相应组件的服务:

// lesson/template.hbs
<h2>{{model.question.lesson.title}}</h2>

<div class="callout"> {{{model.question.body}}} </div>

{{#if model.question.isMultipleChoice}}
    {{answer-multiple-choice-list answers=model.question.answers}}
{{else if model.question.isDragDrop}}
    {{answer-drag-drop question=model.question}}
{{else if model.question.isOpen}}
    {{answer-open-textarea question=model.question checkAnswer="checkAnswer"}}
{{/if}}

{{#if question_is_answered}}
<a class="next button" {{action 'nextQuestion'}}>Next</a>
{{else}}
<a class="check button" {{action 'checkAnswer'}}>Check</a>
{{/if}}

此服务最后还将包含对后端api的ajax请求。

例如,answer-open-textarea组件如下所示:

// lesson/controller.js
export default Ember.Controller.extend({

    lesson: Ember.inject.service(),

    errorObserver: Ember.on('init', Ember.observer('lesson.has_error', function() {
        console.log('Error detected');
    })),

    actions: {
        checkAnswer() {
            this.set('lesson.is_check_pressed', true);
        }
    }

});

验证输入的逻辑应该在组件中,因为对控制器中所有可能的问题类型进行有效性检查是没有意义的。

不幸的是,上面的代码不能按预期的方式工作,即使这只是基本的想法。有效的是,当按下复选按钮时,组件checkObserver会在其登录到控制台时触发。但是,当更新服务中的lesson.has_error时,它不会触发控制器中的errorObserver。而且,即使这样可行,控制器和组件也会有几个观察者,我觉得这不是一个好的解决方案。

我的问题是:控制器和组件如何以适当的方式“沟通”?通过使用服务?如果是,那会是什么样子?我想不是通过Observers。

提前致谢!

1 个答案:

答案 0 :(得分:0)

服务应该是控制器和组件在Ember Universe中直接通信的首选(并且最终是唯一的)方式。但是,我没有发现它们的用法直观,所以我只是做了对我有意义的事情;

Ember希望您遵循“数据向下,动作向上”的模式。这意味着,如果你想在组件中有任何东西,你应该在模板中实例化它时将其传递下去。如果您希望组件影响控制器,则需要传递操作名称,然后调用sendAction以获得所需的效果;

Em.Controller.extend({
  actions: {
    controllerAction: function(){ console.log("you clicked my component"}
  }
})
//template
{{my-component componentAction='controllerAction'}}

Em.Component.extend({
  click: function(){ this.sendAction('componentAction') }

另外一种对这只猫进行修饰的方法是将控制器向下传递到组件中,并直接向组件中的控制器执行操作;

//template 
{{ my-component controller=this }}

这是一个骗子,但它对我有用。快乐的Ember-ing