Angular / TypeScript,当使用多个组件时,第一个组件影响第二个组件

时间:2018-05-17 21:23:12

标签: javascript angular typescript

我创建了一个库Angular-Slickgrid,它是jQuery数据网格库的包装器,是开源的。当页面上只有1个网格(组件),但当我想在同一页面上创建其中2个组件(相同的选择器)时,这一切都很好用,我开始得到很多奇怪的行为。我可以看到的行为是第一个函数中的一些影响第二个网格。我可以处理服务单例,但在我的情况下,它真的是被最后创建的组件覆盖的组件的属性,为什么呢?我认为每个Angular组件都完全独立(除了服务),所以我做错了什么?

我使用ng-packagr创建我的lib,组件的ngModule如下

@NgModule({
  imports: [
    CommonModule,
    TranslateModule
  ],
  declarations: [
    AngularSlickgridComponent,
    SlickPaginationComponent
  ],
  exports: [
    AngularSlickgridComponent,
    SlickPaginationComponent
  ],
  entryComponents: [AngularSlickgridComponent]
})
export class AngularSlickgridModule {
  static forRoot(config: GridOption = {}) {
    return {
      ngModule: AngularSlickgridModule,
      providers: [
        {provide: 'config', useValue: config},
        CollectionService,
        ControlAndPluginService,
        ExportService,
        FilterService,
        GraphqlService,
        GridEventService,
        GridExtraService,
        GridOdataService,
        GridStateService,
        GroupingAndColspanService,
        OdataService,
        ResizerService,
        SharedService,
        SortService
      ]
    };
  }
}

组件类以

开头
@Injectable()
@Component({
  selector: 'angular-slickgrid',
  templateUrl: './angular-slickgrid.component.html',
  providers: [ResizerService]
})
export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnInit {

然后在我的应用程序中,我像这样调用外部网格模块

imports: [
  AppRoutingRoutingModule,
  BrowserModule,
  HttpClientModule,
  TranslateModule.forRoot({
    loader: {
      provide: TranslateLoader,
      useFactory: (createTranslateLoader),
      deps: [HttpClient]
    }
  }),
  AngularSlickgridModule.forRoot({
    // add any Global Grid Options/Config you might wantApp
    enableAutoResize: true
  })
],

然后我可以像我这样在我的视图中创建2个网格

    <angular-slickgrid gridId="grid1"
          [columnDefinitions]="columnDefinitions"
          [gridOptions]="gridOptions"
          gridHeight="200"
        gridWidth="800"
          [dataset]="dataset">
</angular-slickgrid>

<hr>

<angular-slickgrid gridId="grid2"
          [columnDefinitions]="columnDefinitions2"
          [gridOptions]="gridOptions2"
          gridHeight="200"
        gridWidth="800"
          [dataset]="dataset2">
</angular-slickgrid>

在花了很多时间调试之后,我确实发现第一个组件完全覆盖了第二个组件的属性。如果我销毁第二个组件,它不会解决问题。例如,当我点击&#34; clearSort()&#34;时,我点击一列以在两个网格上对其进行排序。从第一个网格,它实际上清除了第二个网格的类型!?我还发现只有最后创建的网格的属性仍然存在,如果我点击&#34; clearSort()&#34;从第一或第二个网格,它将在第二个网格中清除它。

我知道如何处理Services Singleton,但是我的问题实际上是由2个组件以某种方式共享的类的属性...或者将它放在另一个透视图中,第二个组件覆盖了第一个组件类属性特性

我是否缺少使这两个组件完全独立的东西?我一直在寻找和尝试几个小时,是甚至可能还是正常行为?

修改

如果你想查看所有代码,可以从GitHub获得所有代码,你可以看到2个网格代码(目前在一个单独的分支上):

编辑2 经过这几个小时后,我发现 与Services Singleton有关。我在下面回答了我自己的问题。希望这将有助于其他面临类似问题的人。

请参阅下面的行为,观察数据以及蓝色排序图标,当我在第一个网格上执行操作时,这一切都发生在第二个网格上

enter image description here

2 个答案:

答案 0 :(得分:0)

两个组件实例,即使是相同的组件类,也应该有自己的范围。如果它们没有被声明为静态变量,那么它们的变量是封装的和唯一的。

您确定数据集和数据集2不共享相同的引用吗?即使是测试,也要避免跟随:

import time
from machine import Pin
led=Pin(5,Pin.OUT)
BRate=0.25


def morse_dash():
    led.value(1)
    time.sleep(4*BRate)
    led.value(0)
    time.sleep(BRate)

def morse_pause():
    time.sleep(BRate)

def morse_dot():
    led.value(1)
    time.sleep(BRate)
    led.value(0)
    time.sleep(BRate)

CODE = {' ': '_', 
"'": '.----.', 
'(': '-.--.-', 
')': '-.--.-', 
',': '--..--', 
'-': '-....-', 
'.': '.-.-.-', 
'/': '-..-.', 
'0': '-----', 
'1': '.----', 
'2': '..---', 
'3': '...--', 
'4': '....-', 
'5': '.....', 
'6': '-....', 
'7': '--...', 
'8': '---..', 
'9': '----.', 
':': '---...', 
';': '-.-.-.', 
'?': '..--..', 
'A': '.-', 
'B': '-...', 
'C': '-.-.', 
'D': '-..', 
'E': '.', 
'F': '..-.', 
'G': '--.', 
'H': '....', 
'I': '..', 
'J': '.---', 
'K': '-.-', 
'L': '.-..', 
'M': '--', 
'N': '-.', 
'O': '---', 
'P': '.--.', 
'Q': '--.-', 
'R': '.-.', 
'S': '...', 
'T': '-', 
'U': '..-', 
'V': '...-', 
'W': '.--', 
'X': '-..-', 
'Y': '-.--', 
'Z': '--..', 
'_': '..--.-'}

def convertToMorseCode(sentence):
    sentence = sentence.upper()
    encodedSentence = ""
    for character in sentence:
        encodedSentence += CODE[character] + " " 
    return encodedSentence

while True:

    sentence = input("Enter sentence: ")
    encodedSentence = convertToMorseCode(sentence)
    print(encodedSentence)
    for i in encodedSentence:
        if i == ".":
            morse_dot()
        elif i == "-":
            morse_dash()
        else:
            morse_pause()

如果您将数据集和数据集2输入到两个不同的组件,那将强制执行所描述的所需行为。

你正在包装一个jquery插件,它本身就是普通的javascript。也许包装的javascript正在撤销angulars组件范围?

您确定组件实例不会错误地按服务共享数据吗?

答案 1 :(得分:0)

哇我发现了这个问题,我没想到我发现的问题......我的图书馆里面没有providers,所以所有的服务都是单身人士。因此,任何Services函数调用都使用最后创建的网格的内部变量(gridgridOptionsdataView)。因此,为了解决这个问题,我唯一需要做的就是将所有服务提供给providers数组。

<强> BEFORE

@Injectable()
@Component({
  selector: 'angular-slickgrid',
  templateUrl: './angular-slickgrid.component.html',
  providers: [ResizerService]
})

导出类AngularSlickgridComponent实现AfterViewInit,OnDestroy,OnInit {

<强> AFTER

@Injectable()
@Component({
  selector: 'angular-slickgrid',
  templateUrl: './angular-slickgrid.component.html',
  providers: [
    ControlAndPluginService,
    ExportService,
    FilterService,
    GraphqlService,
    GridEventService,
    GridExtraService,
    GridStateService,
    GroupingAndColspanService,
    ResizerService,
    SortService
  ]
})
export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnInit {

哦,我的......为这么简单的事情浪费了这么多时间