У меня есть проект 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(); });
}
}
вы, вероятно, создаете какую-то утечку памяти со всем этим jquery... избавьтесь от всего этого и делайте что-то угловым
Вы действительно имеете в виду, что это из-за кодов jquery?
@thrashead Вы вызвали onCopy(id) в FillData(), а FillData() вызывается в ngOnInit.
Должен ли я сделать это как (щелкнуть) = onCopy (модель? .ID) на стороне html? Это то, что вы имеете в виду?
Итак, когда вы переходите на страницу категории, вызывается onCopy(id). И this.router.navigate(['/'], { skipLocationChange: true }).then(() => { this.router.navigate([currentUrl]) });
сделать цикл зависимым от вызова onCopy(id).
Да, @thrashead, вам не следует вызывать onCopy(id) в ngOnInit()
но он вызывает функцию по щелчку. Есть ли способ удалить его при уничтожении?
Попробуйте обернуть оба сервиса (getIndex() и getCopy()) вот так this.subscription.add( this.service.getIndex().subscribe())
вместо this.subscription = this.service.getIndex().subscribe()
Вот ссылка на RxJS-документация.
я попробовал это человек. это не сработало. я думаю, это из-за вызова onCopy в ngOnInit, как все говорили. Мне нужно решение для удаления прослушивателя кликов.
В общем, вам следует избегать смешивания Angular и jQuery. Здесь ваша конкретная проблема вызвана тем, что вы вызываете this.FillData()
в ngOnInit. Поскольку ngOnInit вызывается каждый раз, когда вы направляетесь на страницу, код в this.FillData()
вызывается каждый раз, когда вы направляетесь.
Поскольку this.FillData()
вызывается неоднократно, каждый раз, когда вы направляетесь на страницу, вы каждый раз подключаете свои обработчики событий в jQuery (таблица данных и клики). Поскольку вы никогда не отсоединяете обработчики событий при маршрутизации, вы в конечном итоге подключаете одно и то же событие несколько раз. Это усугубляется тем фактом, что вы прикрепляете обработчик на уровне документа и используете всплывающее окно событий, вы прикрепляете несколько обработчиков на уровне документа, и каждый раз, когда вы добавляете новый, он вызывается дополнительный раз.
Поскольку вы используете DataTables, я бы посоветовал вам полностью отказаться от кода jQuery и перевести свои обработчики на правильный подход Angular. Существует множество компонентов, подобных DataTables (например, я широко использовал ag-grid).
Если вы должен используете jQuery (по какой-либо причине), вам необходимо реорганизовать свой код, чтобы либо удалить все существующие обработчики событий при маршрутизации к/от компонента. Почти уверен, что вы могли бы просто вставить .off('click')
туда.
$(document).off("click", "a.cpy-yes").on("click", "a.cpy-yes"....
Или вам нужно убедиться, что вы присоединяете обработчики событий однажды только к родительскому компоненту (поскольку вы все равно его поднимаете).
спасибо за Ваш ответ. как убрать обработчики? есть способ?
Отредактировал ответ, вы сможете просто вставить выключение перед включением.
Ты мужчина. ты спас мне жизнь спасибо чувак. Я добавил $(document).off("click", "a.cpyLink"); $(document).off("click", "a.cpy-yes"); коды в функции onCopy() до того, как я вызвал службу, и все готово. еще раз спасибо :)
Что ж, каждый раз, когда компонент инициализируется, он добавляет в документ новый прослушиватель кликов. И это никогда не удаляет слушателя.