使用Ember中的组件生命周期事件

Using component lifecycle events in Ember

本文关键字:生命 周期 事件 组件 Ember 使用      更新时间:2024-03-12

根据最新的Ember文档,不鼓励使用观测器来覆盖组件生命周期挂钩。我不确定的是如何有效地使用这些钩子。文档中说,您可以使用didUpdateAttrsdidReceiveAttrs来替换观察者。

让我们假设我有一个组件,它绘制出一些数据。组件看起来像:

{{my-chart data=data showLabels=showLabels otherProps=otherProps}}

当设置了data时,它需要对数据执行一些分析,因此只有当data是真正的新数据时才会发生这种情况。showLabels属性显示/隐藏图表中的标签,并通过my-chart之外的东西进行切换。

我选择在didReceiveAttrs在初始和后续渲染中运行时使用它,并对其进行了如下编码:

didReceiveAttrs() {
    let data = this.getAttr('data');
    this.performAnalytics(data);
    let showLabels = this.get('showLabels');
    this.updateHideLabels(showLabels);
}

这样做的问题是,每次更改任何属性时,didReceiveAttrs中的所有代码都会运行。因此,如果用户重复执行导致showLabels更改的操作,那么也会调用performAnalytics,这很糟糕,因为它会导致图表刷新。

我的具体问题是,如何使用像didReceiveAttrs这样的生命周期事件作为观察者,以便只有发生更改的属性才能执行其代码路径?

我要说的是,我尝试存储掉属性,并将其与传入属性进行比较,但我觉得这效率很低,尤其是在data的情况下,它是一个复杂对象数组。

您可以编写一个实用程序文件,比如utils/component-lifecycle.js

export const attrsHaveChanged = ((changes, attr) => {
  const { oldAttrs, newAttrs } = changes;
  if (oldAttrs) {
    const oldAttrsValue = JSON.stringify(oldAttrs[attr].value);
    const newAttrsValue = JSON.stringify(newAttrs[attr].value);
    return oldAttrsValue !== newAttrsValue;
  } else {
    return true;
  }
});

现在在你的组件中,你可以导入它,

import { attrsHaveChanged } from 'appname/utils/component-lifecycle';

并使用

didReceiveAttrs(changes) {
  if (attrsHaveChanged(changes, 'chartData')) {
    doSomething();
  }
}