Heim Web-Frontend js-Tutorial Entwicklung von Kerndiensten und Dienstprogrammen in Angular 18

Entwicklung von Kerndiensten und Dienstprogrammen in Angular 18

Sep 13, 2024 pm 10:19 PM

Разработка core сервисов и утилит в Angular 18

Kern ist eine Reihe von Funktionen, Konfigurationen und Dienstprogrammen, die in der Anwendung verwendet werden.

Normalerweise ist der Kern das, was Sie von Projekt zu Projekt ziehen. In diesem Fall habe ich versucht, nur das Nötigste zu nehmen.

Kurz über alles Kernstück:

  • api/params.ts – Dienstprogramm zum Festlegen von Parametern. Beispielsweise gibt es in Abfrageparametern baggage=true, aber true muss kein String, sondern ein boolescher Wert sein;
  • Währung/currency.ts – Währungskonfiguration;
  • env/environment.ts – Abrufen und Verwenden von .env;
  • form/form.ts – eine kleine Eingabe von FormGroup;
  • form/extract-changes.directive.ts – Änderungserkennungsrichtlinie in FormControl;
  • hammer/hammer.ts – hammerjs-Einstellungen;
  • interceptors/content-type.interceptor.ts – Bestimmen des Inhaltstyps für HTTP-Anfragen;
  • Metriken – Dienst zum Senden von Ereignissen an Google Analytics und Yandex-Metriken;
  • navigation/mavigation.ts – Implementierung von Pfaden in der Anwendung;
  • styles/extra-class.service.ts – mein Fahrrad für hängende Kurse;
  • types/type.ts – benutzerdefinierte Typen;
  • Dienstprogramme – Dienstprogramme zum Arbeiten mit Terminen und Fristen.

Nur ​​die Navigation verdient besondere Aufmerksamkeit.

App-Navigation verwalten

Sehen wir uns die Implementierung der Navigationssteuerung genauer an.

Angenommen, wir haben Routen für die gesamte Anwendung:

export const PATHS = {
  home: '',
  homeAvia: '',
  homeHotels: 'hotels',
  homeTours: 'tours',
  homeRailways: 'railways',

  rules: 'rules',
  terms: 'terms',
  documents: 'documents',
  faq: 'faq',
  cards: 'cards',
  login: 'login',
  registration: 'registration',

  notFound: 'not-found',
  serverError: 'server-error',
  permissionDenied: 'permission-denied',

  search: 'search',
  searchAvia: 'search/avia',
  searchHotel: 'search/hotels',
  searchTour: 'search/tours',
  searchRailway: 'search/railways',
} as const;

PathValues ​​​​- ein Typ, der eine Reihe von Zeichenfolgen darstellt.

export type PathValues = (typeof PATHS)[keyof typeof PATHS];

type Filter<T extends string> = T extends `:${infer Param}` ? Param : never;

type Split<Value extends string> = Value extends `${infer LValue}/${infer RValue}` ? Filter<LValue> | Split<RValue> : Filter<Value>;

export type GetPathParams<T extends string> = {
  [key in Split<T>]: string | number;
};

export interface NavigationLink<T extends PathValues = PathValues> {
  readonly label: string;
  readonly route: T;
  readonly params?: GetPathParams<T>;
  readonly suffix?: string;
}

NavigationLink – Link-Array-Schnittstelle.

getRoute teilt die Zeichenfolge mit Parametern auf und ersetzt die gefundenen Schlüssel durch die übergebenen Werte:

export function getRoute<T extends PathValues>(path: T, params: Record<string, string | number> = {}): (string | number)[] {
  const segments = path.split('/').filter((value) => value?.length);
  const routeWithParams: (string | number)[] = ['/'];

  for (const segment of segments) {
    if (segment.charAt(0) === ':') {
      const paramName = segment.slice(1);
      if (params && params[paramName]) {
        routeWithParams.push(params[paramName]);
      } else {
        routeWithParams.push(paramName);
      }
    } else {
      routeWithParams.push(segment);
    }
  }

  return routeWithParams;
}

Neueste Funktionen zum „Formen“ von Pfaden in Anwendungsrouten:

export function getChildPath(path: PathValues, parent: PathValues): string {
  return path.substring(parent.length + 1);
}

export function childNavigation(route: NavigationChild, parent: PathValues): Route {
  const redirectTo = route.redirectTo ? `/${route.redirectTo}` : undefined;

  if (!route.path.length || route.path.length < parent.length + 1) {
    return { ...route, redirectTo };
  }

  return {
    ...route,
    redirectTo,
    path: getChildPath(route.path, parent),
  };
}

export function withChildNavigation(parent: PathValues): (route: NavigationChild) => Route {
  return (route: NavigationChild) => childNavigation(route, parent);
}

Anwendungsbeispiel. In app.routes:

export const routes: Routes = [
  {
    path: '',
    loadComponent: () => import('@baf/ui/layout').then((m) => m.LayoutComponent),
    children: [
      {
        path: PATHS.search,
        loadChildren: () => import('./routes/search.routes').then((m) => m.searchRoutes),
      },
    ],
  },
];

In Routen/search.routes.ts:

import { Routes } from '@angular/router';
import { PATHS, withChildNavigation } from '@baf/core';

export const searchRoutes: Routes = [
  {
    path: PATHS.searchAvia,
    title: $localize`:Search Page:Search for cheap flights`,
    loadComponent: () => import('@baf/search/page').then((m) => m.SearchPageComponent),
  },
].map(withChildNavigation(PATHS.search));

Analytik

Dienst zum Senden von Ereignissen an Google Analytics und Yandex Metrika – Metriken:

import { InjectionToken } from '@angular/core';

export interface MetricConfig {
  readonly ids?: string[];
  readonly counter?: number;
  readonly domains: string[];
  readonly paths: string[];
}

export const METRIC_CONFIG = new InjectionToken<MetricConfig>('MetricConfig');

MetricConfig – Konfiguration von Google- und Yandex-Metriken:

  • ids – Google IDS-Liste;
  • Zähler - Yandex Metrika-Zähler;
  • Domänen – Liste der Domänen zum Kombinieren von Analysesitzungen;
  • Pfade – eine Reihe von Pfaden, wenn Referrer zurückgesetzt werden sollen.

Allgemeiner Service zum Versenden von Ereignissen:

import { inject, Injectable } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs';
import { tap } from 'rxjs/operators';

import { GoogleAnalytics } from './google-analytics';
import { YandexMetrika } from './yandex.metrika';

export interface MetricOptions {
  readonly [key: string]: unknown;

  readonly ym?: Record<string, unknown>;
  readonly ga?: Record<string, unknown>;
}

export function extractOptions(options?: MetricOptions): { readonly ym?: Record<string, unknown>; readonly ga?: Record<string, unknown> } {
  let { ym, ga } = options ?? {};

  if (options) {
    if (!ym && !ga) {
      ym = options;
      ga = options;
    }
  }

  return { ym, ga };
}

@Injectable()
export class MetricService {
  private readonly router = inject(Router);
  private readonly yandexMetrika = inject(YandexMetrika);
  private readonly googleAnalytics = inject(GoogleAnalytics);

  constructor() {
    this.router.events
      .pipe(
        filter((event): event is NavigationEnd => event instanceof NavigationEnd),
        tap((event) => this.navigation(event.urlAfterRedirects)),
        takeUntilDestroyed(),
      )
      .subscribe();
  }

  init(customerId?: string | number) {
    this.set({
      ga: customerId ? { user_id: customerId } : undefined,
      ym: customerId ? { UserID: customerId } : undefined,
    });
  }

  navigation(url: string): void {
    this.googleAnalytics.sendNavigation(url);
    this.yandexMetrika.hit(url);
  }

  send(action: string, options?: MetricOptions): void {
    const params = extractOptions(options);

    this.googleAnalytics.sendEvent(action, params.ga);
    this.yandexMetrika.reachGoal(action, params.ym);
  }

  set(options: MetricOptions): void {
    const params = extractOptions(options);

    if (params.ga) {
      this.googleAnalytics.set(params.ga);
    }
    if (params.ym) {
      this.yandexMetrika.set(params.ym);
    }
  }
}

Servicemethoden:

  • init – Initialisierung der Zähler;
  • Navigation – Senden eines Seitenübergangsereignisses;
  • senden - Registrierungsveranstaltung;
  • set – Übergabe von Parametern an Analytics.

Implementierung des Google Analytics-Dienstes:

import { DOCUMENT, isPlatformBrowser } from '@angular/common';
import { inject, Injectable, PLATFORM_ID } from '@angular/core';
import { Title } from '@angular/platform-browser';

import { METRIC_CONFIG } from './metrica.interface';

declare global {
  interface Window {
    readonly gtag?: (...params: unknown[]) => void;
  }
}

@Injectable()
export class GoogleAnalytics {
  private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
  private readonly document = inject(DOCUMENT);
  private readonly config = inject(METRIC_CONFIG);
  private readonly title = inject(Title);

  readonly gtag: (...params: unknown[]) => void;

  constructor() {
    if (this.isBrowser && typeof this.document.defaultView?.gtag !== 'undefined' && this.config.ids && this.config.ids?.length > 0) {
      this.gtag = this.document.defaultView.gtag;
    } else {
      this.gtag = () => {};
    }
  }

  set(payload: Record<string, unknown>): void {
    this.gtag('set', payload);
  }

  sendEvent(action: string, payload?: Record<string, unknown>): void {
    this.gtag('event', action, {
      ...payload,
      event_category: payload?.['eventCategory'],
      event_label: payload?.['eventLabel'],
      value: payload?.['eventValue'],
    });
  }

  sendNavigation(url: string): void {
    if (
      (this.isBrowser && !this.config.domains.every((domain) => this.document.referrer.indexOf(domain) < 0)) ||
      !this.config.paths.every((path) => this.document.location.pathname.indexOf(path) < 0)
    ) {
      this.set({ page_referrer: this.document.defaultView?.location.origin ?? '' });
    }

    if (this.config.ids) {
      for (const key of this.config.ids) {
        this.gtag('config', key, {
          page_title: this.title.getTitle(),
          page_path: url,
        });
      }
    }
  }
}

Yandex-Metriken:

import { DOCUMENT, isPlatformBrowser } from '@angular/common';
import { inject, Injectable, PLATFORM_ID } from '@angular/core';

import { METRIC_CONFIG } from './metrica.interface';

declare global {
  interface Window {
    readonly ym?: (...params: unknown[]) => void;
  }
}

@Injectable()
export class YandexMetrika {
  private readonly document = inject(DOCUMENT);
  private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
  private readonly config = inject(METRIC_CONFIG);

  private readonly counter: (...params: unknown[]) => void;

  constructor() {
    if (this.isBrowser && typeof this.document.defaultView?.ym !== 'undefined' && !!this.config.counter) {
      this.counter = this.document.defaultView.ym;
    } else {
      this.counter = () => {};
    }
  }

  hit(url: string, options?: Record<string, unknown>): void {
    let clearReferrer = false;
    if (
      (this.isBrowser && !this.config.domains.every((domain) => this.document.referrer.indexOf(domain) < 0)) ||
      !this.config.paths.every((path) => this.document.location.pathname.indexOf(path) < 0)
    ) {
      clearReferrer = true;
    }

    const optionsAll: { referer?: string } = { ...options };
    if (clearReferrer) {
      optionsAll.referer = '';
    }
    this.counter(this.config.counter, 'hit', url, optionsAll);
  }

  reachGoal(target: string, options?: Record<string, unknown>): void {
    this.counter(this.config.counter, 'reachGoal', target, options);
  }

  set(params: Record<string, unknown>, options?: Record<string, unknown>): void {
    this.counter(this.config.counter, 'userParams', params, options);
  }
}

Kern

Dienstprogramm zum Casting von Anforderungsparametern – api/params.ts:

export type HttpParams = Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>>;

export function castParams(all: Record<string, unknown>): HttpParams {
  const params: HttpParams = {};

  for (const [key, value] of Object.entries(all)) {
    if (Array.isArray(value) && value.length > 0) {
      params[key] = value.filter((val) => {
        return typeof val === 'string' || typeof val === 'boolean' || typeof val === 'number';
      });
    } else if (typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number') {
      params[key] = value;
    }
  }

  return params;
}

Währung einstellen – Währung/currency.ts:

import { DEFAULT_CURRENCY_CODE, Provider } from '@angular/core';

export function provideCurrency(currencyCode: string): Provider {
  return {
    provide: DEFAULT_CURRENCY_CODE,
    useValue: currencyCode,
  };
}

Umgebungsvariablen abrufen und verwenden – env/environment.ts:

import type { ApplicationConfig} from '@angular/core';
import { APP_INITIALIZER, makeStateKey, TransferState } from '@angular/core';

export const ENV_KEY = makeStateKey<Environment>('Environment');

export interface Environment {
  readonly aviasalesToken: string;
  readonly hotellookToken: string;
}

export const ENV_DEFAULT: Environment = {
  aviasalesToken: '',
  hotellookToken: '',
};

export function provideEnv() {
  return [
    {
      provide: APP_INITIALIZER,
      useFactory: (transferState: TransferState) => {
        return () => {
          transferState.set<Environment>(ENV_KEY, {
            aviasalesToken: process.env['AVIASALES_TOKEN'] ?? ENV_DEFAULT.aviasalesToken,
            hotellookToken: process.env['HOTELLOOK_TOKEN'] ?? ENV_DEFAULT.hotellookToken,
          });
        };
      },
      deps: [TransferState],
      multi: true,
    },
  ];
}

export const envConfig: ApplicationConfig = {
  providers: [provideEnv()],
};

Formulareingabe – form/form.ts:

import type { FormControl, FormGroup } from '@angular/forms';

export type FormFor<T> = {
  [P in keyof T]: FormControl<T[P]>;
};

export type FormWithSubFor<T> = {
  [P in keyof T]: T[P] extends Record<string, unknown> ? FormGroup<FormFor<T[P]>> : FormControl<T[P]>;
};

export function castQueryParams(queryParams: Record<string, unknown>, props?: string[]): Record<string, unknown> {
  const mapped: Record<string, unknown> = {};

  const keys = props ?? Object.keys(queryParams);

  for (const key of keys) {
    const value = queryParams[key];

    if (typeof value === 'string' && value.length > 0) {
      if (['true', 'false'].includes(value)) {
        mapped[key] = value === 'true';
      } else if (!isNaN(Number(value))) {
        mapped[key] = Number(value);
      } else {
        mapped[key] = value;
      }
    } else if (typeof value === 'boolean') {
      mapped[key] = value;
    } else if (typeof value === 'number' && value > 0) {
      mapped[key] = value;
    }
  }

  return mapped;
}

FormControl-Änderungserkennungsanweisung:

import type { FormControl, FormGroup } from '@angular/forms';

export type FormFor<T> = {
  [P in keyof T]: FormControl<T[P]>;
};

export type FormWithSubFor<T> = {
  [P in keyof T]: T[P] extends Record<string, unknown> ? FormGroup<FormFor<T[P]>> : FormControl<T[P]>;
};

export function castQueryParams(queryParams: Record<string, unknown>, props?: string[]): Record<string, unknown> {
  const mapped: Record<string, unknown> = {};

  const keys = props ?? Object.keys(queryParams);

  for (const key of keys) {
    const value = queryParams[key];

    if (typeof value === 'string' && value.length > 0) {
      if (['true', 'false'].includes(value)) {
        mapped[key] = value === 'true';
      } else if (!isNaN(Number(value))) {
        mapped[key] = Number(value);
      } else {
        mapped[key] = value;
      }
    } else if (typeof value === 'boolean') {
      mapped[key] = value;
    } else if (typeof value === 'number' && value > 0) {
      mapped[key] = value;
    }
  }

  return mapped;
}

Hammerjs-Setup:

import type { EnvironmentProviders, Provider } from '@angular/core';
import { importProvidersFrom, Injectable } from '@angular/core';
import { HAMMER_GESTURE_CONFIG, HammerGestureConfig, HammerModule } from '@angular/platform-browser';

@Injectable()
export class HammerConfig extends HammerGestureConfig {
  override overrides = {
    swipe: { velocity: 0.4, threshold: 20 },
    pinch: { enable: false },
    rotate: { enable: false },
  };
}

export function provideHammer(): (Provider | EnvironmentProviders)[] {
  return [
    importProvidersFrom(HammerModule),
    {
      provide: HAMMER_GESTURE_CONFIG,
      useClass: HammerConfig,
    },
  ];
}

Inhaltstyp für HTTP-Anfragen festlegen -interceptors/content-type.interceptor.ts:

import type { HttpInterceptorFn } from '@angular/common/http';

export const contentTypeInterceptor: HttpInterceptorFn = (req, next) => {
  if (!req.headers.has('Content-Type') && req.headers.get('enctype') !== 'multipart/form-data') {
    req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
  }

  return next(req);
};

Dienst zum Hinzufügen von Klassen zu Komponenten und Anweisungen – Styles/extra-class.service.ts:

import { DestroyRef, ElementRef, inject, Injectable, Renderer2 } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import type { Observable, Subscription } from 'rxjs';
import { tap } from 'rxjs';

type Styles = string | string[] | undefined | null;

export function toClass(value: unknown | undefined | null, prefix = 'is'): Styles {
  return value ? `${prefix}-${value}` : undefined;
}

@Injectable()
export class ExtraClassService {
  private readonly destroyRef = inject(DestroyRef);
  private readonly render = inject(Renderer2);
  private readonly elementRef: ElementRef<HTMLElement> = inject(ElementRef);

  private styles: Record<string, Styles> = {};
  private subscriptions: Record<string, Subscription> = {};

  update(key: string, styles: Styles): void {
    if (this.styles[key]) {
      const lastStyles = this.styles[key];
      if (Array.isArray(lastStyles)) {
        lastStyles.map((style) => this.render.removeClass(this.elementRef.nativeElement, style));
      } else if (lastStyles) {
        this.render.removeClass(this.elementRef.nativeElement, lastStyles);
      }
    }
    if (Array.isArray(styles)) {
      styles.map((style) => this.render.addClass(this.elementRef.nativeElement, style));
    } else if (styles) {
      this.render.addClass(this.elementRef.nativeElement, styles);
    }
    this.styles[key] = styles;
  }

  patch(style: string, active: boolean): void {
    if (active) {
      this.render.addClass(this.elementRef.nativeElement, style);
    } else {
      this.render.removeClass(this.elementRef.nativeElement, style);
    }
  }

  register(key: string, observable: Observable<unknown>, callback: () => void, start = true): void {
    if (this.subscriptions[key]) {
      this.unregister(key);
    }
    if (start) {
      callback();
    }
    this.subscriptions[key] = observable
      .pipe(
        tap(() => callback()),
        takeUntilDestroyed(this.destroyRef),
      )
      .subscribe();
  }

  unregister(key: string): void {
    this.subscriptions[key].unsubscribe();
  }
}

Benutzerdefinierte Typen –types/type.ts:

export type ChangeFn = (value: any) => void;

export type TouchedFn = () => void;

export type DisplayFn = (value: any, index?: number) => string;

export type MaskFn = (value: any) => string;

export type StyleFn = (value?: any) => string | string[];

export type CoerceBoolean = boolean | string | undefined | null;

Dienstprogramme zum Arbeiten mit Terminen und Fristen – Dienstprogramme:

export function getDaysBetweenDates(startDate: Date | string, endDate: Date | string): number {
  return Math.round((new Date(endDate).getTime() - new Date(startDate).getTime()) / 86400000);
}

Короткая реализация для uuid:

export function uuidv4(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;

    const v = c == 'x' ? r : (r & 0x3) | 0x8;

    return v.toString(16);
  });
}

И функция для гуманизации:

export function camelCaseToHumanize(str: string): string {
  return str.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
}

В следующей статье будем разрабатывать свой UI KIT.

Ссылки

Все исходники находятся на github, в репозитории - github.com/Fafnur/buy-and-fly

Демо можно посмотреть здесь - buy-and-fly.fafn.ru/

Мои группы: telegram, medium, vk, x.com, linkedin, site

Das obige ist der detaillierte Inhalt vonEntwicklung von Kerndiensten und Dienstprogrammen in Angular 18. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Warum sollten Sie  Tags am Ende des  platzieren? Warum sollten Sie Tags am Ende des platzieren? Jul 02, 2025 am 01:22 AM

PlatztagsattheBottomofabogpostorwebpageServeSpracticalPurposesforseo, Usexperience und design.1ithelpswithseobyallowingEnginestoaccessKeyword-relevantTagswithoutClutteringHemainContent.2.

Wie arbeite man mit Daten und Zeiten in JS? Wie arbeite man mit Daten und Zeiten in JS? Jul 01, 2025 am 01:27 AM

Die folgenden Punkte sollten bei der Verarbeitung von Daten und Zeiten in JavaScript festgestellt werden: 1. Es gibt viele Möglichkeiten, Datumsobjekte zu erstellen. Es wird empfohlen, ISO -Format -Zeichenfolgen zu verwenden, um die Kompatibilität sicherzustellen. 2. Die Zeitinformationen erhalten und festlegen können und setzen Sie Methoden fest, und beachten Sie, dass der Monat mit 0 beginnt. 3. Die manuell formatierende Daten sind Zeichenfolgen erforderlich, und auch Bibliotheken von Drittanbietern können verwendet werden. 4. Es wird empfohlen, Bibliotheken zu verwenden, die Zeitzonen wie Luxon unterstützen. Das Beherrschen dieser wichtigen Punkte kann häufige Fehler effektiv vermeiden.

Was sprudelt und fängt Ereignis im Dom? Was sprudelt und fängt Ereignis im Dom? Jul 02, 2025 am 01:19 AM

Ereigniserfassung und Blase sind zwei Phasen der Ereignisausbreitung in DOM. Die Erfassung erfolgt von der oberen Schicht bis zum Zielelement, und die Blase ist vom Zielelement bis zur oberen Schicht. 1. Die Ereigniserfassung wird implementiert, indem der UseCapture -Parameter von AddEventListener auf true festgelegt wird. 2. Ereignisblase ist das Standardverhalten, Uscapture ist auf false oder weggelassen. 3. Die Ereignisausbreitung kann verwendet werden, um die Ereignisausbreitung zu verhindern. 4. Event Bubbling unterstützt die Ereignisdelegation, um die Effizienz der dynamischen Inhaltsverarbeitung zu verbessern. 5. Capture kann verwendet werden, um Ereignisse im Voraus abzufangen, wie z. B. Protokollierung oder Fehlerverarbeitung. Das Verständnis dieser beiden Phasen hilft dabei, das Timing und die Reaktion von JavaScript auf Benutzeroperationen genau zu steuern.

Eine endgültige JS -Zusammenfassung auf JavaScript -Modulen: ES -Module gegen CommonJs Eine endgültige JS -Zusammenfassung auf JavaScript -Modulen: ES -Module gegen CommonJs Jul 02, 2025 am 01:28 AM

Der Hauptunterschied zwischen ES -Modul und CommonJs ist das Lademethode und das Nutzungsszenario. 1.Kommonjs ist synchron geladen und für die node.js server-Seite-Umgebung geeignet. 2. Das Modul ist asynchron geladen und für Netzwerkumgebungen wie Browser geeignet. A. 4.Commonjs wird in alten Versionen von Node.js und Bibliotheken, die auf IT wie Express angewiesen sind, häufig verwendet, während ES-Module für moderne Front-End-Frameworks und Node.jsv14 geeignet sind; 5. Obwohl es gemischt werden kann, kann es leicht zu Problemen führen.

Wie funktioniert die Müllsammlung in JavaScript? Wie funktioniert die Müllsammlung in JavaScript? Jul 04, 2025 am 12:42 AM

Der Müllsammlung von JavaScript verwaltet den Speicher automatisch über einen Tag-Clearing-Algorithmus, um das Risiko eines Speicherlecks zu verringern. Der Motor durchquert und markiert das aktive Objekt aus dem Wurzelobjekt, und nicht markiert wird als Müll behandelt und gelöscht. Wenn das Objekt beispielsweise nicht mehr referenziert wird (z. B. die Variable nach NULL), wird es in der nächsten Runde des Recyclings freigegeben. Zu den häufigen Ursachen für Speicherlecks gehören: ① Ungeräte Timer oder Event -Hörer; ② Verweise auf externe Variablen in Schließungen; ③ Globale Variablen halten weiterhin eine große Datenmenge. Der V8 -Motor optimiert die Recyclingeffizienz durch Strategien wie Recycling von Generationen, inkrementelle Markierung, paralleles/gleichzeitiges Recycling und verkürzt die Hauptblockierungszeit. Während der Entwicklung sollten unnötige globale Referenzen vermieden und Objektverbände umgehend dekoriert werden, um die Leistung und Stabilität zu verbessern.

Wie stelle ich eine HTTP -Anforderung in node.js? Wie stelle ich eine HTTP -Anforderung in node.js? Jul 13, 2025 am 02:18 AM

Es gibt drei gängige Möglichkeiten, HTTP-Anforderungen in Node.js zu initiieren: Verwenden Sie integrierte Module, Axios und Knotenfetch. 1. Verwenden Sie das integrierte HTTP/HTTPS-Modul ohne Abhängigkeiten, das für grundlegende Szenarien geeignet ist, jedoch eine manuelle Verarbeitung von Datengenähten und Fehlerüberwachung erfordert, z. 2.Axios ist eine auf Versprechen basierende Bibliothek von Drittanbietern. Es verfügt über eine kurze Syntax und leistungsstarke Funktionen, unterstützt Async/Auseait, automatische JSON -Konvertierung, Interceptor usw. Es wird empfohlen, asynchrone Anforderungsvorgänge zu vereinfachen. 3.Node-Fetch bietet einen Stil ähnlich dem Browser-Abruf, basierend auf Versprechen und einfacher Syntax

var vs let vs const: ein kurzer JS -Roundup Explarer var vs let vs const: ein kurzer JS -Roundup Explarer Jul 02, 2025 am 01:18 AM

Der Unterschied zwischen VaR, LET und CONT ist Geltungsbereich, Werbung und wiederholte Erklärungen. 1.VAR ist das Funktionsbereich mit variabler Werbung, die wiederholte Deklarationen ermöglicht. 2. Das Glied ist der Umfang auf Blockebene mit vorübergehenden toten Zonen, und wiederholte Erklärungen sind nicht zulässig. 3.Konst ist auch der Umfang auf Blockebene und muss sofort zugewiesen werden und kann nicht neu zugewiesen werden, aber der interne Wert des Referenztyps kann geändert werden. Verwenden Sie zuerst const, verwenden Sie LET, wenn Sie Variablen ändern, und vermeiden Sie die Verwendung von VAR.

Warum ist Dom Manipulation langsam und wie kann sie optimiert werden? Warum ist Dom Manipulation langsam und wie kann sie optimiert werden? Jul 01, 2025 am 01:28 AM

Die Hauptgründe für den langsamen Betrieb von DOM sind die hohen Kosten für die Umlagerung, die Neuausrichtung und den niedrigen Zugangseffizienz. Zu den Optimierungsmethoden gehören: 1. Reduzieren Sie die Anzahl der Zugriffe und Cache -Lesewerte; 2. Batch -Lesen und Schreibvorgänge; 3.. Zusammenführen und ändern, Dokumentfragmente oder verborgene Elemente verwenden; V. 5. Verwenden Sie Framework oder RequestAnimationFrame Asynchronous Update.

See all articles