我是Ember的新手,有一个泄露状态的问题。我有一个carousel小部件,它一次显示一个项目,并允许用户单击上一个/下一个来查看每个项目。
下面是简化的carousel组件:
<button {{action "nextItem"}}>Next</button>
{{carousel-item item=selectedItem}}单击next会更改selectedItem属性,以便显示下一项。
我意识到,并不是每次我移动到上一项/下一项时,carousel-item组件都会重新初始化。DOM每次都会被重用,组件的属性也是共享的,因为它都是一个实例,这意味着我可能会有泄漏状态。
我看到的另一种选择是最初呈现所有项,这样每个项都有自己的实例:
{{#each items as |item|}}
{{carousel-item item=item}}
{{/each}}并使用CSS隐藏除所选项目之外的所有项目。然而,这个选项有点像jQuery黑客--似乎Ember有更好的方法。而且我一次只显示一个项目,所以我讨厌在不需要的时候有这么多额外的DOM节点。
如果一次只需要显示一个项目,但又不想在项目之间共享状态,那么处理这种UI的推荐方式是什么?我想我应该为每个项目都有一个carousel-item组件的实例,而不是在所有项目之间共享一个实例。但是一开始实例化每一个carousel-item也是不对的。我不能想象Ember的方式是自己过多地担心DOM的细节(根据一个类和一些CSS来决定显示/隐藏哪一个)。
发布于 2017-04-18 11:12:58
首先,无论你使用的是什么框架或库,jQuery、ember、angular、react,它们都只是一包JS/HTML/CSS,对吧?所以你应该以它的方式思考,没有魔法!
所以,当然1个组件只能创建1个实例。如果你只是改变了它的属性(在你的演示中),它只是改变了一个实例的属性,它的其他属性将保持不变,并触发重新渲染。你不能期待更多。您必须手动重置其他属性。
是的,用{{each}}渲染一切看起来很愚蠢,但想想看,你怎么能通过只渲染一个DOM来创建平滑的旋转木马动画呢?至少你需要渲染3个(当前,上一个和下一个),对吗?
由于carousel是一个常见的UI,我建议你在自己写之前先检查一下现有的ember插件:https://emberobserver.com/?query=carousel
发布于 2017-04-18 11:13:46
如果我正确理解了您的问题,Ember.Component类中的willUpdate钩子应该可以帮助您解决问题。在这个钩子中,你可以清除属性,删除DOM对象,或者做任何事情。这将在每次组件将要重新呈现其自身时被调用。
下面是一个简单的例子:
willUpdate() {
Ember.$(this.get('element')).empty();
},这将在每次重新渲染时清除DOM,强制它重新绘制元素。
您也可以尝试其他钩子,看看哪个事件可以满足您的需求。它们都是非常有用的,并且服务于不同的目的。
https://stackoverflow.com/questions/43459975
复制相似问题