Angular 路由更改后多次调用服务函数
Angular service function being called multiple times after route change
我有一个 angular 8 项目。它具有复制数据的服务功能。当我复制数据并转到另一页时,如果我再次返回同一页并再次复制数据,它会复制数据两次。如果我再做一次,它会多次调用服务函数并多次复制数据。
我尝试了很多不同的方法,但它仍然多次复制数据。希望你能理解我的要求。我在等你的答案和解决方案。
这是我的 app.module.ts 代码;
import { APP_BASE_HREF } from '@angular/common';
import { NgModule } from '@angular/core';
import { ModuleWithProviders } from '@angular/compiler/src/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app';
import { CategoryComponent } from './views/category';
import { CategoryService } from './services/category';
@NgModule({
declarations: [
AppComponent,
CategoryComponent
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }),
HttpClientModule
],
providers: [{ provide: APP_BASE_HREF, useValue: '/AngularProject/' }, CategoryService ],
bootstrap: [AppComponent]
})
export class AppModule { }
这是我的服务代码;
import { Injectable } from "@angular/core";
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ICategory } from '../models/ICategory';
@Injectable({ providedIn: 'root' })
export class CategoryService {
private linkIndex: string = "Ajax/Category/Index";
private linkCopy: string = "Ajax/Category/Copy";
constructor(private http: HttpClient) {
}
getIndex(): Observable<Array<ICategory>> {
return this.http.get<Array<ICategory>>(this.linkIndex);
}
getCopy(id: string): Observable<boolean> {
let params = new HttpParams().set("id", id);
return this.http.get<boolean>(this.linkCopy, { params: params });
}
}
这是我的 CategoryComponent 代码;
import { Component, OnDestroy, OnInit } from "@angular/core";
import { Subscription } from "rxjs";
import { Router } from "@angular/router";
import { CategoryService } from "../../services/category";
import * as $ from "jquery";
@Component({
templateUrl: './index.html'
})
export class CategoryComponent implements OnInit, OnDestroy {
errorMsg: string;
CategoryList: any;
callTable: boolean;
private subscription: Subscription = new Subscription();
constructor(private service: CategoryService, private router: Router) {
}
ngOnInit() {
this.callTable = true;
this.FillData();
}
FillData() {
if (this.callTable == true) {
this.subscription = this.service.getIndex().subscribe((answer) => {
this.CategoryList = answer;
this.callTable = false;
setTimeout(() => {
$(".data-table").dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"sDom": '<""l>t<"F"fp>'
});
$(document).on("click", "a.cpyLink", function () {
$(this).addClass("active-cpy");
$("a.cpy-yes").attr("data-id", $(this).attr("data-id"));
});
$(document).on("click", "a.cpy-yes", () => {
let id: string = $("a.cpy-yes").attr("data-id");
this.onCopy(id);
});
}, 1);
}, resError => this.errorMsg = resError, () => { this.subscription.unsubscribe(); });
}
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
onCopy(id) {
this.subscription = this.service.getCopy(id).subscribe((answer) => {
if (answer == true) {
let currentUrl = this.router.url;
this.router.navigate(['/'], { skipLocationChange: true }).then(() => { this.router.navigate([currentUrl]) });
}
}, resError => this.errorMsg = resError, () => { this.subscription.unsubscribe(); });
}
}
一般来说,您应该避免混合使用 Angular 和 jQuery。在这里,您的特定问题是因为您在 ngOnInit 中调用 this.FillData()
引起的。由于每次路由到页面时都会调用 ngOnInit,因此每次路由时都会调用 this.FillData()
中的代码。
由于 this.FillData()
被重复调用,每次路由到页面时,您每次都将事件处理程序附加到 jQuery(数据表和 onclicks)中。由于您在路由离开时从不分离事件处理程序,因此您最终会多次附加相同的事件。由于您在文档级别附加处理程序并使用 event bubbling,您在文档级别附加多个处理程序,并且每次添加新的处理程序时,这会变得更糟,它被称为额外的时间。
由于您使用的是数据表,我建议您完全删除 jQuery 代码并将处理程序转换为正确的 Angular 方法。那里有很多类似 DataTables 的组件(例如,我广泛使用了 ag-grid)。
如果您必须使用jQuery(无论出于何种原因),那么您需要重构代码以在路由[=32=时删除任何现有的事件处理程序] 组件。很确定你可以在里面放一个 .off('click')
。
$(document).off("click", "a.cpy-yes").on("click", "a.cpy-yes"....
或者您需要确保只在父组件中附加事件处理程序 一次(因为无论如何您都在冒泡)。
我有一个 angular 8 项目。它具有复制数据的服务功能。当我复制数据并转到另一页时,如果我再次返回同一页并再次复制数据,它会复制数据两次。如果我再做一次,它会多次调用服务函数并多次复制数据。
我尝试了很多不同的方法,但它仍然多次复制数据。希望你能理解我的要求。我在等你的答案和解决方案。
这是我的 app.module.ts 代码;
import { APP_BASE_HREF } from '@angular/common';
import { NgModule } from '@angular/core';
import { ModuleWithProviders } from '@angular/compiler/src/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app';
import { CategoryComponent } from './views/category';
import { CategoryService } from './services/category';
@NgModule({
declarations: [
AppComponent,
CategoryComponent
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }),
HttpClientModule
],
providers: [{ provide: APP_BASE_HREF, useValue: '/AngularProject/' }, CategoryService ],
bootstrap: [AppComponent]
})
export class AppModule { }
这是我的服务代码;
import { Injectable } from "@angular/core";
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ICategory } from '../models/ICategory';
@Injectable({ providedIn: 'root' })
export class CategoryService {
private linkIndex: string = "Ajax/Category/Index";
private linkCopy: string = "Ajax/Category/Copy";
constructor(private http: HttpClient) {
}
getIndex(): Observable<Array<ICategory>> {
return this.http.get<Array<ICategory>>(this.linkIndex);
}
getCopy(id: string): Observable<boolean> {
let params = new HttpParams().set("id", id);
return this.http.get<boolean>(this.linkCopy, { params: params });
}
}
这是我的 CategoryComponent 代码;
import { Component, OnDestroy, OnInit } from "@angular/core";
import { Subscription } from "rxjs";
import { Router } from "@angular/router";
import { CategoryService } from "../../services/category";
import * as $ from "jquery";
@Component({
templateUrl: './index.html'
})
export class CategoryComponent implements OnInit, OnDestroy {
errorMsg: string;
CategoryList: any;
callTable: boolean;
private subscription: Subscription = new Subscription();
constructor(private service: CategoryService, private router: Router) {
}
ngOnInit() {
this.callTable = true;
this.FillData();
}
FillData() {
if (this.callTable == true) {
this.subscription = this.service.getIndex().subscribe((answer) => {
this.CategoryList = answer;
this.callTable = false;
setTimeout(() => {
$(".data-table").dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"sDom": '<""l>t<"F"fp>'
});
$(document).on("click", "a.cpyLink", function () {
$(this).addClass("active-cpy");
$("a.cpy-yes").attr("data-id", $(this).attr("data-id"));
});
$(document).on("click", "a.cpy-yes", () => {
let id: string = $("a.cpy-yes").attr("data-id");
this.onCopy(id);
});
}, 1);
}, resError => this.errorMsg = resError, () => { this.subscription.unsubscribe(); });
}
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
onCopy(id) {
this.subscription = this.service.getCopy(id).subscribe((answer) => {
if (answer == true) {
let currentUrl = this.router.url;
this.router.navigate(['/'], { skipLocationChange: true }).then(() => { this.router.navigate([currentUrl]) });
}
}, resError => this.errorMsg = resError, () => { this.subscription.unsubscribe(); });
}
}
一般来说,您应该避免混合使用 Angular 和 jQuery。在这里,您的特定问题是因为您在 ngOnInit 中调用 this.FillData()
引起的。由于每次路由到页面时都会调用 ngOnInit,因此每次路由时都会调用 this.FillData()
中的代码。
由于 this.FillData()
被重复调用,每次路由到页面时,您每次都将事件处理程序附加到 jQuery(数据表和 onclicks)中。由于您在路由离开时从不分离事件处理程序,因此您最终会多次附加相同的事件。由于您在文档级别附加处理程序并使用 event bubbling,您在文档级别附加多个处理程序,并且每次添加新的处理程序时,这会变得更糟,它被称为额外的时间。
由于您使用的是数据表,我建议您完全删除 jQuery 代码并将处理程序转换为正确的 Angular 方法。那里有很多类似 DataTables 的组件(例如,我广泛使用了 ag-grid)。
如果您必须使用jQuery(无论出于何种原因),那么您需要重构代码以在路由[=32=时删除任何现有的事件处理程序] 组件。很确定你可以在里面放一个 .off('click')
。
$(document).off("click", "a.cpy-yes").on("click", "a.cpy-yes"....
或者您需要确保只在父组件中附加事件处理程序 一次(因为无论如何您都在冒泡)。