我是Ember的新手并且有一个泄漏状态问题。我有一个轮播小部件,一次显示一个项目,允许用户点击上一个/下一个查看每个项目。
这是简化的轮播组件:
await Body.Add(sigPad1 = new SignaturePad { Id = "sigPad1", Enabled = true, LineThickness = 4 }
.Set(x => x.Style.Border.Color = "red")
.Set(x => x.Style.Width = 100)
.Set(x => x.Style.Height = 100));
点击<button {{action "nextItem"}}>Next</button>
{{carousel-item item=selectedItem}}
会更改next
属性,以便显示下一个项目。
我意识到每次移动到上一个/下一个项目时都不会重新初始化selectedItem
组件。 DOM每次都被重用,组件的属性是共享的,因为它只是一个实例,这意味着我可以有泄漏状态。
我看到的替代方案是最初渲染所有项目,因此每个项目都有自己的实例:
carousel-item
并使用CSS隐藏除选定项目之外的所有项目。然而,这种选择感觉就像一个jQuery黑客 - 似乎Ember会有更好的方式。我一次只展示一个项目,所以当我不需要时,我讨厌拥有这么多额外的DOM节点。
处理这种UI的推荐方法是什么,您只需要一次显示一个项目,但又不想在项目之间共享状态?我想我每个项目应该有一个{{#each items as |item|}}
{{carousel-item item=item}}
{{/each}}
组件的实例,而不是在所有项目中共享一个实例。但是,最初也不一定要实例化每一个carousel-item
。我无法想象Ember的方式是自己过多地关注DOM细节(根据类和一些CSS确定显示/隐藏哪一个)。
答案 0 :(得分:0)
首先,无论你使用的是什么框架或库,jQuery,ember,angular,react,它们只是一包JS / HTML / CSS吧?所以你应该考虑一下,没有魔法!
当然,1个组件只会创建1个实例。如果您刚刚更改了它的属性(演示中的 item ),它只是更改了实例的属性,它的其他属性将保持不变并触发重新渲染。你不能指望更多。您必须手动重置其他属性。
是的,通过{{each}}
呈现所有内容看起来很愚蠢,但想一想,你怎么能通过渲染一个DOM创建一个流畅的轮播动画?至少你需要渲染3(当前,上一个和下一个)吗?
由于轮播是一个常见的用户界面,我建议您在自己写作之前检查现有的余烬插件:https://emberobserver.com/?query=carousel
答案 1 :(得分:0)
如果我正确理解了您的问题,Ember.Component类中的willUpdate挂钩应该会帮助您。我这个钩子你可以清理属性,删除DOM对象,或任何东西。每次组件即将重新渲染时,都会调用它。
一个简单的例子是:
{{1}}
这将清除每次重新渲染时的DOM,强制它重绘元素。
你也可以尝试其他钩子,看看哪个事件将满足你的需要。所有这些都非常有用,并且有不同的用途。