【问题标题】:Shared state in Ember componentEmber 组件中的共享状态
【发布时间】:2013-09-28 19:26:28
【问题描述】:

我试图用附加小部件作为 Emberjs 组件构建一个简单的列表。

以下是我使用的代码:

HTML:

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/ember.js/1.0.0/ember.min.js"></script>
<meta charset=utf-8 />
<title>Ember Component example</title>
</head>
<body>

  <script type="text/x-handlebars" id="components/appendable-list">
     <h2> An appendable list </h2>
     <ul> 
       {{#each item in myList}}
         <li> {{item}} </li>
       {{/each}} 
     </ul>
     {{input type="text" value=newItem}}
     <button {{action 'append'}}> Append Item </button>
  </script>

  <script type="text/x-handlebars">
    {{appendable-list}}
    {{appendable-list}}
  </script>

</body>
</html>

Javascript:

App = Ember.Application.create();

App.AppendableListComponent = Ember.Component.extend({
    theList: Ember.ArrayProxy.create({ content: [] }),
    actions: {
        appendItem: function(){
            var newItem = this.get('newItem');
            this.get('theList').pushObject(newItem);
        }
    }
});

在这种情况下,列表在两个实例之间共享(即在一个实例中追加在另一个实例中)

这里是 JsBin 检查它:http://jsbin.com/arACoqa/7/edit?html,js,output

如果我执行以下操作,它会起作用:

window.App = Ember.Application.create();

App.AppendableListComponent = Ember.Component.extend({
  didInsertElement: function(){
    this.set('myList', Ember.ArrayProxy.create({content: []}));
  },
  actions: {
    append: function(){
      var newItem = this.get('newItem');
      this.get('myList').pushObject(newItem);
    }
  }
});

这里是 JsBin:http://jsbin.com/arACoqa/8/edit?html,js,output

我做错了什么?提前致谢!

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    声明组件后,每次在模板中使用它都会创建一个新实例,最重要的是,每次实例化新实例时也会调用 init 钩子,因此是最安全的方法有不同的myList 数组将使用组件init 钩子来初始化数组,因此请尝试以下操作:

    App.AppendableListComponent = Ember.Component.extend({
      myList: null,
      init: function(){
        this._super();
        this.set('myList', Ember.ArrayProxy.create({content: []}));
      },
      actions: {
        append: function(){
          var newItem = this.get('newItem');
          this.get('myList').pushObject(newItem);
        }
      }
    });
    

    同样重要的是在init 中调用this._super();,一切都会按预期进行。

    查看这里以获取有效的demo

    希望对你有帮助。

    【讨论】:

    • 太棒了!我认为你的方式更清洁。谢谢!
    • 糟糕!我可以发誓我做到了。希望它是固定的。
    【解决方案2】:

    当您使用extend(hash) 时,哈希中存在的任何值都将被复制到任何创建的实例中。并且因为数组是一个对象,所以您在创建的对象中的引用将是相同的:

    App.MyObject = Ember.Object.extend({ text: [] });
    
    obj1 = App.MyObject.create();
    obj2 = App.MyObject.create();
    
    obj1.get('text') === obj2.get('text') // true
    
    obj1.get('text').pushObject('lorem');
    obj1.get('text'); // ["lorem"]
    
    obj2.get('text').pushObject('ipsum');
    obj2.get('text'); // ["lorem", "ipsum"]
    

    每个创建的新视图都会调用didInsertElement,每个视图都是一个不同的实例。因此,在您的实现中,每个视图都会有一个新的 Ember.ArrayProxy 实例,然后不存在共享状态:

    didInsertElement: function() {
        // each call for this method have a diferent instance
        this.set('myList', Ember.ArrayProxy.create({content: []}));
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      • 2021-07-28
      • 2019-01-31
      • 1970-01-01
      • 2020-08-07
      相关资源
      最近更新 更多