【问题标题】:Ember.js Controller & View Binding (The ember.js way...)Ember.js 控制器和视图绑定(ember.js 方式...)
【发布时间】:2013-03-11 10:57:22
【问题描述】:

对于这个问题的长度,我深表歉意,但我缺乏将其缩短的洞察力。

我正在尝试学习 Ember.js,但我在理解控制器和它的视图之间的关系时遇到了一些麻烦。特别是因为它与控制器属性和视图绑定有关。我有一个工作的应用程序......但我真的不明白为什么&我觉得(很明显)这不是'Ember.js '的方式来做到这一点。

需要考虑的一些事情:根据我在指南/文档中解释为“正确”结构的内容,此应用程序被分解为目录/文件,此应用程序在 sinatra 应用程序的上下文中运行。这个应用程序虽然不完整,但到目前为止确实按我预期的方式工作。

申请不完整,但这里是对我的期望和我正在尝试做的事情的一般概述:

1) 用户到达根 URL '/' 并转换到 '/locate' URL。

2) LocateController 获取用户位置,用 lat/lng 填充两个表单字段。

3) 表单以 POST 形式提交到服务器,以 ajax 形式发送到 sinatra '/locate' 路由。

(请求由服务器处理)

4) 用户被转换到 ember.js '#/located' 路由。

5) 信息作为 JSON 对象从服务器返回并显示

到目前为止,我只实施了第一步。如果我添加了提交按钮,可以发送表单,但想法是让它自动发生。

定位视图中的字段填充了表单字段的正确值。但是,我使用直接 jQuery 来更新值,在我看来,这不是在 ember.js 应用程序中执行此操作的“正确”方式

下面是我的一些代码。为简洁起见,我将仅提供 sn-ps,因为我觉得如果您知道正确的答案,您将能够从提供的摘录中得出它。

我的视图是这样设置的: 我在我的 sinatra 应用中使用 slim

script type="text/x-handlebars" data-template-name="application"
    | {{ outlet }}
script type="text/x-handlebars" data-template-name="locate"
    | {{ message }}
    | <form id="coordinates">
    |     {{view Ember.TextField id="latitude" name="latitude" valueBinding="latitude" class="latitude"}}
    |     {{view Ember.TextField id="longitude" name="longitude" valueBinding="longitude" class="longitude"}}
    | </form>
 script type="text/x-handlebars" data-template-name="located"
    | <p id="message">{{ message }}</p>
    | <p id="latitude">{{ latitude }}</p>
    | <p id="longitude">{{ longitude }}</p>

脚本 src="assets/js/app/application.js"

applicationView.js

Application.ApplicationView = Ember.View.extend({
  templateName: 'application'
});

Application.LocateView = ApplicationView.extend({
  templateName: 'locate'
});

Application.LocatedView = ApplicationView.extend({
  templateName: 'located'
});

applicationController.js

var GeoLocation;

GeoLocation = (function(location){
    $('#latitude').val(location.coords.latitude),
    $('#longitude').val(location.coords.longitude)
});

navigator.geolocation.getCurrentPosition(GeoLocation)

Application.ApplicationController = Ember.Controller.extend({
  message: "Hello from Application"
});

Application.LocateController = Ember.Controller.extend({
    message: "Hello from Locate",
    latitude: "-- lat --", 
    longitude: "-- lng --",
});

Application.LocatedController = Ember.Controller.extend({
    message: "Hello from Located",
    latitude: "-- lat --",
    longitude: "-- lng --",
});

路由器.js

Application.Router.map(function() {
  this.route('index');
  this.route('locate');
  this.route('located');
});

Application.ApplicationRoute = Ember.Route.extend({
  events: {
    goToLocate: function() {
      this.transitionTo('locate');
    },
    goToLocated: function() {
      this.transitionTo('located');
    }
  }
});

Application.IndexRoute = Ember.Route.extend({
  redirect: function() {
        this.render('application');
    this.transitionTo('locate');
  }
});

Application.LocateRoute = Ember.Route.extend({
  redirect: function() {
        this.render('locate');
    //this.transitionTo('located');
  }
});

});

Application.LocatedRoute = Ember.Route.extend({
  renderTemplate: function(controller) {
    this.render('located');
  }
});

我已经阅读了 ember.js 网站上的指南和 API 文档,并查看了 GitHub 上的 repo。我觉得“正确”的实现会为纬度和经度属性使用计算属性,但我不太明白它在实践中是如何工作的。

另外,我知道很可能有更好的方法来处理将信息发送到服务器(可能是 JSON 或 ember-data,当我做到这一点时?),并随时分享您可能有的任何见解关于那个。但是现在,由于我对 sinatra 及其工作方式感到满意,我更喜欢一个不需要对我的后端进行重大重构的解决方案。 (也就是说,能够从 sinatra 的 params[:hash] 访问位置数据)。

提前感谢您的帮助和花时间阅读这个相当长的问题。

【问题讨论】:

    标签: javascript ajax ember.js sinatra


    【解决方案1】:

    我同意在 ember 应用程序中通过 jQuery 设置输入值不是可行的方法。 Ember 在绑定到属性方面做得非常好。 我建议由于您在初始加载时重定向到 Locate 路由,因此将 getLoaction 逻辑移动到 LocateController 或将其设置在路由 setupController 挂钩中,请参见此处(see here for setupController example)...您还可以在您的 App 实例上设置属性,如果您想访问它们。

    所以,不要这样:

    var GeoLocation;
    
    GeoLocation = (function(location){
        $('#latitude').val(location.coords.latitude),
        $('#longitude').val(location.coords.longitude)
    });
    
    navigator.geolocation.getCurrentPosition(GeoLocation)
    

    我会在路线上这样做:

    App.LocateRoute = Ember.Route.extend({
      setupController: function(controller, model) {
        navigator.geolocation.getCurrentPosition(controller.geoLocation)
      }
    });
    
    App.LocateController = Ember.Controller.extend({
      geoLocation: function(location){
        this.set('latitude', location.coords.latitude);
        this.set('longitude', location.coords.longitude);
      }
    });
    

    现在您的定位控制器已定义 2 个属性“纬度”和“经度”。您可以在模板中绑定到它们。 (顺便说一句,您的模板已经看起来适合绑定。)

    如果您想全局访问它们,您还可以在您的 App 实例上设置属性 this,然后将绑定更改为指向“App.longitude”和“App.latitude”。

    App.LocateController = Ember.Controller.extend({
      geoLocation: function(location){
        Ember.set(App, 'latitude', location.coords.latitude);
        Ember.set(App, 'longitude', location.coords.longitude);
      }
    });
    

    【讨论】:

    • 这正是我想要的!太感谢了!我知道直接 jQuery 不是答案。
    • 所以,我认为这意味着使用直接 jQuery 将表单作为 ajax 发送也不是答案。 ember中是否有针对该案件的程序?如此简单且依赖于实例的东西似乎也应该存在于我的路由或控制器中?还是我应该开始考虑开发一些模型?
    • 看来我说得太早了 =/ 我确实认为您的解决方案似乎是正确的。但是,将您的代码添加到我的应用程序并注释掉我的 GeoLocation jQuery 位会使我的文本字段为空。
    • @DonGraziano 是的,您将使用一个操作 (emberjs.com/guides/templates/actions) 来提交您的表单。
    • @DonGraziano 你能提供一个简单的 jsFiddle 或 jsBin 吗?
    猜你喜欢
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2012-03-22
    相关资源
    最近更新 更多