Angular:使用ChangeDetectionStrategy.OnPush进行模型侦听

时间:2019-03-11 23:02:42

标签: angular rxjs angular2-changedetection

假设我有一个大型的Json模型,我的后端发送到我的前端,它看起来像这样:

{
     dataA: { //some object },
     dataB: { //some object },
     dataC: { //some object },
     ...
}

现在让我说我有一个将dataA用作@Input()的ComponentA,将一个dataB用作@Input()的ComponentB,等等:

@Component({
    selector: 'comp-a'
})
class ComponentA {
    @Input() _dataA;
}

@Component({
    selector: 'comp-b'
})
class ComponentA {
    @Input() _dataB;
}

// .... other components

@Component({
    selector: 'app',
    template:`
        <comp-a [_dataA]="dataA"></comp-a>
        <comp-b [_dataB]="dataB"></comp-b>
        ...
    `
})
class AppComponent {
}

我想让这些组件使用OnPush更改检测策略。

收到新模型时,可能发生的情况是该模型中的数据字段未从先前模型中的先前值更改,因此我不希望将它们作为@Input()再次传递给组件,从而避免无所事事地进行变更检测。

在将作为@Input()的数据传递给组件之前,是否有某种聪明的方法可以检测前端模型的更改,并仅在它们各自的数据更改时通知它们?还是应该让Angular自己执行更改检测? OnPush在这里真的合适吗?

1 个答案:

答案 0 :(得分:0)

OnPush通过不检查模型属性来提高效率,并在更改对象实例(而不是对象属性)时触发更新。要执行您建议的操作,将涉及检查对象的属性以查看是否有任何更改。您基本上将重新发明变更检测功能,所以我不明白这一点,并且您需要做得比Angular团队做得更好,才能看到任何好处。

您还用rxjs标记了此问题,但问题中与rxjs无关。实现OnPush更改检测的最佳方法是使用rxjs observables并在模板中使用异步管道。这样,您只能获得可观察到的值以​​发出更新的值。

CXX     libavdevice/decklink_common.o
cc1plus: warning: command line option ‘-Wdeclaration-after-statement’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wmissing-prototypes’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wno-pointer-to-int-cast’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wno-pointer-sign’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-std=c11’ is valid for C/ObjC but not for C++
In file included from libavdevice/decklink_common.cpp:54:0:
libavdevice/decklink_common.h:90:5: error: ‘IDeckLinkAttributes’ does not name a type
     IDeckLinkAttributes *attr;
     ^~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp: In function ‘int decklink_get_attr_string(IDeckLink*, BMDDeckLinkAttributeID, const char**)’:
libavdevice/decklink_common.cpp:84:5: error: ‘IDeckLinkAttributes’ was not declared in this scope
     IDeckLinkAttributes *attr;
     ^~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp:84:26: error: ‘attr’ was not declared in this scope
     IDeckLinkAttributes *attr;
                          ^~~~
libavdevice/decklink_common.cpp:86:28: error: ‘IID_IDeckLinkAttributes’ was not declared in this scope
     if (dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&attr) != S_OK)
                            ^~~~~~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp: In function ‘int decklink_select_input(AVFormatContext*, BMDDeckLinkConfigurationID)’:
libavdevice/decklink_common.cpp:112:20: error: ‘struct decklink_ctx’ has no member named ‘attr’
         res = ctx->attr->GetInt(attr_id, &supported_connections);
                    ^~~~
libavdevice/decklink_common.cpp: In function ‘int ff_decklink_set_configs(AVFormatContext*, decklink_direction_t)’:
libavdevice/decklink_common.cpp:152:18: error: ‘struct decklink_ctx’ has no member named ‘attr’
         if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK)
                  ^~~~
libavdevice/decklink_common.cpp:152:32: error: ‘BMDDeckLinkSupportsDuplexModeConfiguration’ was not declared in this scope
         if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK)
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp:156:36: error: ‘bmdDeckLinkConfigDuplexMode’ was not declared in this scope
             res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp:156:89: error: ‘bmdDuplexModeFull’ was not declared in this scope
             res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
                                                                                         ^~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp:156:109: error: ‘bmdDuplexModeHalf’ was not declared in this scope
             res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
                                                                                                             ^~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp: In function ‘int ff_decklink_set_format(AVFormatContext*, int, int, int, int, AVFieldOrder, decklink_direction_t, int)’:
libavdevice/decklink_common.cpp:190:5: error: ‘BMDDisplayModeSupport’ was not declared in this scope
     BMDDisplayModeSupport support;
     ^~~~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp:254:45: error: ‘support’ was not declared in this scope
                                            &support, NULL) != S_OK)
                                             ^~~~~~~
libavdevice/decklink_common.cpp:259:68: error: ‘support’ was not declared in this scope
                                                                   &support, NULL) != S_OK) {
                                                                    ^~~~~~~
libavdevice/decklink_common.cpp:270:9: error: ‘support’ was not declared in this scope
     if (support == bmdDisplayModeSupported)
         ^~~~~~~
libavdevice/decklink_common.cpp:270:20: error: ‘bmdDisplayModeSupported’ was not declared in this scope
     if (support == bmdDisplayModeSupported)
                    ^~~~~~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp: In function ‘void ff_decklink_cleanup(AVFormatContext*)’:
libavdevice/decklink_common.cpp:434:14: error: ‘struct decklink_ctx’ has no member named ‘attr’
     if (ctx->attr)
              ^~~~
libavdevice/decklink_common.cpp:435:14: error: ‘struct decklink_ctx’ has no member named ‘attr’
         ctx->attr->Release();
              ^~~~
libavdevice/decklink_common.cpp: In function ‘int ff_decklink_init_device(AVFormatContext*, const char*)’:
libavdevice/decklink_common.cpp:476:33: error: ‘IID_IDeckLinkAttributes’ was not declared in this scope
     if (ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&ctx->attr) != S_OK) {
                                 ^~~~~~~~~~~~~~~~~~~~~~~
libavdevice/decklink_common.cpp:476:73: error: ‘struct decklink_ctx’ has no member named ‘attr’
     if (ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&ctx->attr) != S_OK) {
                                                                         ^~~~
ffbuild/common.mak:63: recipe for target 'libavdevice/decklink_common.o' failed
make: *** [libavdevice/decklink_common.o] Error 1