【问题标题】:EmberJS - Text Binding Not WorkingEmberJS - 文本绑定不起作用
【发布时间】:2014-05-11 11:05:20
【问题描述】:

好的,让我先说我对 Ember 完全陌生。我正在度过一段有趣的时光,只是试图让一个基本的绑定工作。这是我的相关代码:

App.js

var App = Ember.Application.create({
    rootElement: '#emberApp'
});

还有 routes.js:

App.Router.map(function () {

});

App.IndexRoute = Ember.Route.extend({
    model: function () {
        return { Foo: 3 };
    }
});

然后这是我的 HTML 文档:

<div id="emberApp"></div>

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/handlebars.js"></script>
<script src="~/Scripts/ember-1.4.0.js"></script>
<script src="~/Scripts/EmberApp.js"></script>
<script src="~/Scripts/Routes.js"></script>

<script type="text/x-handlebars" data-template-name="index">
    <div>The current foo value: {{Foo}}</div>
    {{input valueBinding=Foo}}
</script>

预期的结果是,当我在创建的输入字段中键入时,模板中绑定的值会同时发生变化。应该很简单吧?我必须错过一些东西。

模板正确呈现The current foo value: 3,并呈现一个文本字段。但是,在此字段中输入任何内容对上述绑定没有任何作用。我尝试用valueBinding 标签标记它,以及切换到Ember.TextField 而不是input 助手。我也尝试过创建一个自定义 Ember.Object.extend 类并将其作为索引路由的模型返回。

为了将文本框值绑定到模板中的 {{Foo}} 值,我缺少什么?

编辑 - 好的,我发现这是因为变量的大写:foo 有效,但 Foo 无效。这是为什么呢?

我希望收到类似于此的 JSON 结果:

 {
     RemoteUserId: 0,
     UserPhotoUrl: '....',
     RemoteUserName: 'Bob',
 }

我假设这意味着我需要通过为每个元素制作控制器包装器来“隐藏”这些值?即:

 remoteUserId: function() {
      return this.get('RemoteUserId');
   }.property()

【问题讨论】:

  • 如果您使用的是 ember 数据,您可能希望在适配器级别进行处理。类似于 ams 适配器如何处理蛇壳和骆驼壳。如果您正在滚动自己的模型跟踪,则可能会采用类似的想法。

标签: javascript data-binding ember.js


【解决方案1】:

这是因为在 Ember 中属性应该以小写字母开头!大写字母是全局的。

所以你可以简单地将你的 JSON 转换成 ember:

var decapitalize = function(source) {
  var result = {};
  for(var prop in source) {
    result[prop.substr(0,1).toLowerCase() + prop.substr(1)] = source[prop];
  }
  return result;
};

【讨论】:

    【解决方案2】:

    恐怕您已经被 Embers 命名约定之一所困扰,这通常很棒,因为它通常意味着事情可以正常工作,但如果您不知道它偶尔会咬您。

    Ember 期望类或命名空间大写,实例小写。当 Ember 看到绑定中使用的 Foo 属性时,它会假定它是一个命名空间,然后会查找名为 Foo 的全局变量而不是控制器属性。

    当您在模板中使用{{Foo}} 时,行为会略有不同,因为 Ember 将首先检查当前上下文(控制器)以查看该属性是否存在于那里。如果它确实使用该值,否则它将假定它是一个命名空间并在全局范围内查找它。由于性能问题,绑定不像模板那样工作,因为您不想检查两个位置以获取绑定中可能非常频繁更新的值(例如正在输入的文本框)。

    这就是为什么您可以在模板中使用Foo 并且它可以工作的原因:

    <script type="text/x-handlebars" data-template-name="index">
        <!-- This works! -->
        <div>The current foo value: {{Foo}}</div>   
    </script>
    

    但是当您尝试使用 Foo 作为绑定的一部分时,它将不起作用:

    <script type="text/x-handlebars" data-template-name="index">
         <!-- This doesn't work as Ember thinks Foo is global (i.e., a namespace) -->
         {{input valueBinding=Foo}}
    </script>
    

    最好的办法是遵循 ember 约定并确保所有属性名称都以小写字符开头。但是,如果您想继续在控制器中使用以大写字符开头的属性,那么当您尝试在绑定中使用它时,您需要明确告诉 Ember 该属性来自控制器并且不是全局的:

    <script type="text/x-handlebars" data-template-name="index">
         <!-- Tell Ember Foo is in the controller which is what we want-->
         {{input valueBinding=controller.Foo}}
    </script>
    

    这是一个 Fiddle,展示了上面写的所有内容:

    http://jsfiddle.net/NQKvy/881/

    【讨论】:

    • 太好了,这很好地解释了事情。另外,我不必在所有控制器上编写包装器来“隐藏”错误命名的属性!
    猜你喜欢
    • 2013-02-01
    • 2015-08-12
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-29
    • 2012-02-10
    • 1970-01-01
    相关资源
    最近更新 更多