【问题标题】:Ember component leaking stateEmber 组件泄漏状态
【发布时间】:2017-04-17 21:32:10
【问题描述】:

我是 Ember 新手,遇到了泄漏状态问题。我有一个轮播小部件,一次显示一个项目,并允许用户单击上一个/下一个来查看每个项目。

这是简化的轮播组件:

<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 hack —— 似乎 Ember 会有更好的方法。而且我一次只显示一个项目,所以当我不需要它们时,我讨厌有这么多额外的 DOM 节点。

处理这种 UI 的推荐方法是什么,您一次只需要显示一个项目,但不想在项目之间共享状态?我想我应该每个项目都有一个 carousel-item 组件的实例,而不是在所有项目之间共享一个实例。但是一开始实例化每个carousel-item 也不对。而且我无法想象 Ember 的方式是我自己过多地担心 DOM 细节(根据类和一些 CSS 确定显示/隐藏哪个)。

【问题讨论】:

  • 我不明白您泄漏的实际状态是什么?状态不是从item 派生的吗?

标签: javascript ember.js


【解决方案1】:

首先,无论您使用什么框架或库,jQuery、ember、angular、react,它们只是一组 JS/HTML/CSS 对吧?所以你应该以它的方式思考,没有魔法!

所以当然 1 个组件只会创建 1 个实例。如果您只是更改了它的属性(item 在您的演示中),它只是更改了实例的属性,它的其他属性将保持原样并触发重新渲染。你不能期待更多。您必须手动重置其他属性。

是的,通过{{each}} 渲染所有内容看起来很愚蠢,但想想看,你怎么能通过只渲染一个 DOM 来创建流畅的轮播动画呢?至少您需要渲染 3(当前、上一个和下一个)对吗?

由于轮播是一个常见的 UI,我建议你在自己编写之前检查现有的 ember 插件:https://emberobserver.com/?query=carousel

【讨论】:

    【解决方案2】:

    如果我正确理解了您的问题,Ember.Component 类中的 willUpdate 钩子应该可以帮助您。通过这个钩子,您可以清除属性、删除 DOM 对象或任何事情。每次组件将要重新渲染自己时都会调用它。

    一个简单的例子如下:

    willUpdate() {
        Ember.$(this.get('element')).empty();
      },
    

    这将在每次重新渲染时清除 DOM,强制它重新绘制元素。

    您也可以尝试其他钩子,看看哪个事件可以满足您的需求。他们都非常有帮助,并且服务于不同的目的。

    【讨论】:

      猜你喜欢
      • 2016-01-20
      • 2017-10-24
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      • 2020-03-28
      相关资源
      最近更新 更多