ist jetzt verfügbar! Lesen Sie über die neuen Funktionen und Fehlerbehebungen vom November.

Webview API

Die Webview API ermöglicht es Erweiterungen, vollständig anpassbare Ansichten innerhalb von Visual Studio Code zu erstellen. Zum Beispiel verwendet die integrierte Markdown-Erweiterung Webviews, um Markdown-Vorschauen zu rendern. Webviews können auch verwendet werden, um komplexe Benutzeroberflächen zu erstellen, die über die nativen VS Code-APIs hinausgehen.

Stellen Sie sich ein Webview als ein iframe innerhalb von VS Code vor, das Ihre Erweiterung steuert. Ein Webview kann fast jeden HTML-Inhalt in diesem Frame rendern und kommuniziert mit Erweiterungen über Message Passing. Diese Freiheit macht Webviews unglaublich leistungsfähig und eröffnet eine völlig neue Bandbreite an Erweiterungsmöglichkeiten.

Webviews werden in verschiedenen VS Code APIs verwendet

  • Mit Webview-Panels, die mit createWebviewPanel erstellt werden. In diesem Fall werden Webview-Panels als eigenständige Editoren in VS Code angezeigt. Dies macht sie nützlich für die Anzeige von benutzerdefinierten UIs und benutzerdefinierten Visualisierungen.
  • Als Ansicht für einen benutzerdefinierten Editor. Benutzerdefinierte Editoren ermöglichen es Erweiterungen, eine benutzerdefinierte Benutzeroberfläche zum Bearbeiten jeder Datei im Arbeitsbereich bereitzustellen. Die Custom Editor API ermöglicht es Ihrer Erweiterung auch, sich in Editor-Ereignisse wie Rückgängigmachen und Wiederherstellen sowie in Datei-Ereignisse wie Speichern einzuklinken.
  • In Webview-Ansichten, die in den Seitenleisten- oder Panelbereichen gerendert werden. Weitere Details finden Sie in der Webview View Sample Extension.

Diese Seite konzentriert sich auf die grundlegende Webview Panel API, obwohl fast alles, was hier behandelt wird, auch für Webviews gilt, die in benutzerdefinierten Editoren und Webview-Ansichten verwendet werden. Auch wenn Sie sich mehr für diese APIs interessieren, empfehlen wir Ihnen, diese Seite zuerst zu lesen, um sich mit den Grundlagen von Webviews vertraut zu machen.

Verwendung der VS Code API

Sollten Sie ein Webview verwenden?

Webviews sind ziemlich erstaunlich, sollten aber auch sparsam und nur dann eingesetzt werden, wenn die native API von VS Code nicht ausreicht. Webviews sind ressourcenintensiv und laufen in einem separaten Kontext von normalen Erweiterungen. Ein schlecht gestaltetes Webview kann sich auch leicht fehl am Platz fühlen innerhalb von VS Code.

Bevor Sie ein Webview verwenden, bedenken Sie bitte Folgendes

  • Muss diese Funktionalität wirklich innerhalb von VS Code leben? Wäre sie besser als eigenständige Anwendung oder Website?

  • Ist ein Webview der einzige Weg, Ihr Feature zu implementieren? Können Sie stattdessen die regulären VS Code APIs verwenden?

  • Wird Ihr Webview genügend Benutzernutzen hinzufügen, um seinen hohen Ressourcenaufwand zu rechtfertigen?

Denken Sie daran: Nur weil Sie etwas mit Webviews tun können, heißt das nicht, dass Sie es tun sollten. Wenn Sie jedoch zuversichtlich sind, dass Sie Webviews verwenden müssen, dann ist dieses Dokument hier, um Ihnen zu helfen. Lassen Sie uns beginnen.

Grundlagen der Webviews API

Um die Webview API zu erklären, werden wir eine einfache Erweiterung namens Cat Coding erstellen. Diese Erweiterung wird ein Webview verwenden, um ein GIF einer Katze zu zeigen, die Code schreibt (vermutlich in VS Code). Während wir die API durcharbeiten, werden wir die Funktionalität der Erweiterung erweitern, einschließlich eines Zählers, der die Anzahl der Quellcodezeilen verfolgt, die unsere Katze geschrieben hat, und Benachrichtigungen, die den Benutzer informieren, wenn die Katze einen Fehler einführt.

Hier ist die package.json für die erste Version der Cat Coding-Erweiterung. Den vollständigen Code für die Beispiel-App finden Sie hier. Die erste Version unserer Erweiterung stellt einen Befehl namens catCoding.start bereit. Wenn ein Benutzer diesen Befehl aufruft, zeigen wir ein einfaches Webview mit unserer Katze an. Benutzer können diesen Befehl aus der Befehlspalette als Cat Coding: Start new cat coding session aufrufen oder sogar eine Tastenkombination dafür erstellen, wenn sie dazu geneigt sind.

{
  "name": "cat-coding",
  "description": "Cat Coding",
  "version": "0.0.1",
  "publisher": "bierner",
  "engines": {
    "vscode": "^1.74.0"
  },
  "activationEvents": [],
  "main": "./out/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "catCoding.start",
        "title": "Start new cat coding session",
        "category": "Cat Coding"
      }
    ]
  },
  "scripts": {
    "vscode:prepublish": "tsc -p ./",
    "compile": "tsc -watch -p ./",
    "postinstall": "node ./node_modules/vscode/bin/install"
  },
  "dependencies": {
    "vscode": "*"
  },
  "devDependencies": {
    "@types/node": "^9.4.6",
    "typescript": "^2.8.3"
  }
}

Hinweis: Wenn Ihre Erweiterung eine VS Code-Version vor 1.74 anvisiert, müssen Sie onCommand:catCoding.start explizit in activationEvents auflisten.

Lassen Sie uns nun den Befehl catCoding.start implementieren. In der Hauptdatei unserer Erweiterung registrieren wir den Befehl catCoding.start und verwenden ihn, um ein grundlegendes Webview anzuzeigen.

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      // Create and show a new webview
      const panel = vscode.window.createWebviewPanel(
        'catCoding', // Identifies the type of the webview. Used internally
        'Cat Coding', // Title of the panel displayed to the user
        vscode.ViewColumn.One, // Editor column to show the new webview panel in.
        {} // Webview options. More on these later.
      );
    })
  );
}

Die Funktion vscode.window.createWebviewPanel erstellt und zeigt ein Webview im Editor an. Hier sehen Sie, was passiert, wenn Sie den Befehl catCoding.start in seinem aktuellen Zustand ausführen.

An empty webview

Unser Befehl öffnet ein neues Webview-Panel mit dem korrekten Titel, aber ohne Inhalt! Um unsere Katze zum neuen Panel hinzuzufügen, müssen wir auch den HTML-Inhalt des Webviews mit webview.html festlegen.

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      // Create and show panel
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {}
      );

      // And set its HTML content
      panel.webview.html = getWebviewContent();
    })
  );
}

function getWebviewContent() {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width="300" />
</body>
</html>`;
}

Wenn Sie den Befehl erneut ausführen, sieht das Webview nun so aus.

A webview with some HTML

Fortschritt!

webview.html sollte immer ein vollständiges HTML-Dokument sein. HTML-Fragmente oder fehlerhaftes HTML können zu unerwartetem Verhalten führen.

Webview-Inhalt aktualisieren

webview.html kann auch den Inhalt eines Webviews aktualisieren, nachdem es erstellt wurde. Lassen Sie uns dies nutzen, um Cat Coding dynamischer zu gestalten, indem wir eine Rotation von Katzen einführen.

import * as vscode from 'vscode';

const cats = {
  'Coding Cat': 'https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
  'Compiling Cat': 'https://media.giphy.com/media/mlvseq9yvZhba/giphy.gif'
};

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {}
      );

      let iteration = 0;
      const updateWebview = () => {
        const cat = iteration++ % 2 ? 'Compiling Cat' : 'Coding Cat';
        panel.title = cat;
        panel.webview.html = getWebviewContent(cat);
      };

      // Set initial content
      updateWebview();

      // And schedule updates to the content every second
      setInterval(updateWebview, 1000);
    })
  );
}

function getWebviewContent(cat: keyof typeof cats) {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="${cats[cat]}" width="300" />
</body>
</html>`;
}

Updating the webview content

Das Setzen von webview.html ersetzt den gesamten Webview-Inhalt, ähnlich wie beim Neuladen eines iframes. Dies ist wichtig zu beachten, sobald Sie Skripte in einem Webview verwenden, da das Setzen von webview.html auch den Skriptzustand zurücksetzt.

Das obige Beispiel verwendet auch webview.title, um den Titel des im Editor angezeigten Dokuments zu ändern. Das Setzen des Titels führt nicht dazu, dass das Webview neu geladen wird.

Lebenszyklus

Webview-Panels gehören zu der Erweiterung, die sie erstellt. Die Erweiterung muss das von createWebviewPanel zurückgegebene Webview festhalten. Wenn Ihre Erweiterung diese Referenz verliert, kann sie keinen Zugriff mehr auf dieses Webview erhalten, obwohl das Webview weiterhin in VS Code angezeigt wird.

Wie bei Texteditoren kann ein Benutzer auch jederzeit ein Webview-Panel schließen. Wenn ein Webview-Panel vom Benutzer geschlossen wird, wird das Webview selbst zerstört. Der Versuch, ein zerstörtes Webview zu verwenden, löst eine Ausnahme aus. Das bedeutet, dass das obige Beispiel mit setInterval tatsächlich einen wichtigen Fehler enthält: Wenn der Benutzer das Panel schließt, wird setInterval weiterhin ausgelöst und versucht, panel.webview.html zu aktualisieren, was natürlich eine Ausnahme auslöst. Katzen hassen Ausnahmen. Lassen Sie uns das beheben!

Das Ereignis onDidDispose wird ausgelöst, wenn ein Webview zerstört wird. Wir können dieses Ereignis verwenden, um weitere Aktualisierungen abzubrechen und die Ressourcen des Webviews zu bereinigen.

import * as vscode from 'vscode';

const cats = {
  'Coding Cat': 'https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
  'Compiling Cat': 'https://media.giphy.com/media/mlvseq9yvZhba/giphy.gif'
};

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {}
      );

      let iteration = 0;
      const updateWebview = () => {
        const cat = iteration++ % 2 ? 'Compiling Cat' : 'Coding Cat';
        panel.title = cat;
        panel.webview.html = getWebviewContent(cat);
      };

      updateWebview();
      const interval = setInterval(updateWebview, 1000);

      panel.onDidDispose(
        () => {
          // When the panel is closed, cancel any future updates to the webview content
          clearInterval(interval);
        },
        null,
        context.subscriptions
      );
    })
  );
}

Erweiterungen können Webviews auch programmatisch schließen, indem sie dispose() darauf aufrufen. Wenn wir zum Beispiel die Arbeitszeit unserer Katze auf fünf Sekunden beschränken wollen.

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {}
      );

      panel.webview.html = getWebviewContent('Coding Cat');

      // After 5sec, programmatically close the webview panel
      const timeout = setTimeout(() => panel.dispose(), 5000);

      panel.onDidDispose(
        () => {
          // Handle user closing panel before the 5sec have passed
          clearTimeout(timeout);
        },
        null,
        context.subscriptions
      );
    })
  );
}

Sichtbarkeit und Verschieben

Wenn ein Webview-Panel in einen Hintergrund-Tab verschoben wird, wird es unsichtbar. Es wird jedoch nicht zerstört. VS Code stellt den Inhalt des Webviews aus webview.html automatisch wieder her, wenn das Panel wieder in den Vordergrund gebracht wird.

Webview content is automatically restored when the webview becomes visible again

Die Eigenschaft .visible gibt an, ob das Webview-Panel derzeit sichtbar ist oder nicht.

Erweiterungen können ein Webview-Panel programmatisch in den Vordergrund bringen, indem sie reveal() aufrufen. Diese Methode nimmt eine optionale Ziel-Ansichtspalte an, um das Panel dort anzuzeigen. Ein Webview-Panel kann zu einem Zeitpunkt nur in einer einzigen Editor-Spalte angezeigt werden. Das Aufrufen von reveal() oder das Ziehen eines Webview-Panels in eine neue Editor-Spalte verschiebt das Webview in diese neue Spalte.

Webviews are moved when you drag them between tabs

Lassen Sie uns unsere Erweiterung so aktualisieren, dass nur ein Webview gleichzeitig existieren kann. Wenn das Panel im Hintergrund ist, holt der Befehl catCoding.start es in den Vordergrund.

export function activate(context: vscode.ExtensionContext) {
  // Track the current panel with a webview
  let currentPanel: vscode.WebviewPanel | undefined = undefined;

  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const columnToShowIn = vscode.window.activeTextEditor
        ? vscode.window.activeTextEditor.viewColumn
        : undefined;

      if (currentPanel) {
        // If we already have a panel, show it in the target column
        currentPanel.reveal(columnToShowIn);
      } else {
        // Otherwise, create a new panel
        currentPanel = vscode.window.createWebviewPanel(
          'catCoding',
          'Cat Coding',
          columnToShowIn || vscode.ViewColumn.One,
          {}
        );
        currentPanel.webview.html = getWebviewContent('Coding Cat');

        // Reset when the current panel is closed
        currentPanel.onDidDispose(
          () => {
            currentPanel = undefined;
          },
          null,
          context.subscriptions
        );
      }
    })
  );
}

Hier ist die neue Erweiterung in Aktion.

Using a single panel and reveal

Immer wenn sich die Sichtbarkeit eines Webviews ändert oder wenn ein Webview in eine neue Spalte verschoben wird, wird das Ereignis onDidChangeViewState ausgelöst. Unsere Erweiterung kann dieses Ereignis nutzen, um Katzen zu wechseln, basierend darauf, in welcher Spalte das Webview angezeigt wird.

const cats = {
  'Coding Cat': 'https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
  'Compiling Cat': 'https://media.giphy.com/media/mlvseq9yvZhba/giphy.gif',
  'Testing Cat': 'https://media.giphy.com/media/3oriO0OEd9QIDdllqo/giphy.gif'
};

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {}
      );
      panel.webview.html = getWebviewContent('Coding Cat');

      // Update contents based on view state changes
      panel.onDidChangeViewState(
        e => {
          const panel = e.webviewPanel;
          switch (panel.viewColumn) {
            case vscode.ViewColumn.One:
              updateWebviewForCat(panel, 'Coding Cat');
              return;

            case vscode.ViewColumn.Two:
              updateWebviewForCat(panel, 'Compiling Cat');
              return;

            case vscode.ViewColumn.Three:
              updateWebviewForCat(panel, 'Testing Cat');
              return;
          }
        },
        null,
        context.subscriptions
      );
    })
  );
}

function updateWebviewForCat(panel: vscode.WebviewPanel, catName: keyof typeof cats) {
  panel.title = catName;
  panel.webview.html = getWebviewContent(catName);
}

Responding to onDidChangeViewState events

Webviews inspizieren und debuggen

Der Befehl Developer: Toggle Developer Tools öffnet ein Entwicklerwerkzeugfenster, das Sie zum Debuggen und Inspizieren Ihrer Webviews verwenden können.

The developer tools

Beachten Sie, dass Sie, wenn Sie eine VS Code-Version älter als 1.56 verwenden oder versuchen, ein Webview zu debuggen, das enableFindWidget setzt, stattdessen den Befehl Developer: Open Webview Developer Tools verwenden müssen. Dieser Befehl öffnet eine dedizierte Entwicklerwerkzeugseite für jedes Webview, anstatt eine Entwicklerwerkzeugseite zu verwenden, die von allen Webviews und dem Editor selbst gemeinsam genutzt wird.

Von den Entwicklerwerkzeugen aus können Sie mit dem Inspektionswerkzeug in der oberen linken Ecke des Entwicklerwerkzeugfensters beginnen, den Inhalt Ihres Webviews zu inspizieren.

Inspecting a webview using the developer tools

Sie können auch alle Fehler und Protokolle Ihres Webviews in der Konsole der Entwicklerwerkzeuge einsehen.

The developer tools console

Um einen Ausdruck im Kontext Ihres Webviews auszuwerten, stellen Sie sicher, dass Sie die Umgebung des **aktiven Frames** aus dem Dropdown-Menü in der oberen linken Ecke des Konsolenbereichs der Entwicklerwerkzeuge auswählen.

Selecting the active frame

Die Umgebung des **aktiven Frames** ist der Ort, an dem die Skripte des Webviews selbst ausgeführt werden.

Außerdem lädt der Befehl Developer: Reload Webview alle aktiven Webviews neu. Dies kann hilfreich sein, wenn Sie den Zustand eines Webviews zurücksetzen müssen oder wenn sich der Webview-Inhalt auf der Festplatte geändert hat und Sie möchten, dass der neue Inhalt geladen wird.

Lokale Inhalte laden

Webviews laufen in isolierten Kontexten, die nicht direkt auf lokale Ressourcen zugreifen können. Dies geschieht aus Sicherheitsgründen. Das bedeutet, dass Sie, um Bilder, Stylesheets und andere Ressourcen von Ihrer Erweiterung zu laden oder Inhalte aus dem aktuellen Arbeitsbereich des Benutzers zu laden, die Funktion Webview.asWebviewUri verwenden müssen, um eine lokale file: URI in eine spezielle URI umzuwandeln, die VS Code zum Laden einer Teilmenge lokaler Ressourcen verwenden kann.

Stellen Sie sich vor, wir möchten die Katzen-GIFs in unsere Erweiterung einbinden, anstatt sie von Giphy zu beziehen. Dazu erstellen wir zunächst eine URI zur Datei auf der Festplatte und geben diese URIs dann durch die Funktion asWebviewUri.

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {}
      );

      // Get path to resource on disk
      const onDiskPath = vscode.Uri.joinPath(context.extensionUri, 'media', 'cat.gif');

      // And get the special URI to use with the webview
      const catGifSrc = panel.webview.asWebviewUri(onDiskPath);

      panel.webview.html = getWebviewContent(catGifSrc);
    })
  );
}

function getWebviewContent(catGifSrc: vscode.Uri) {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="${catGifSrc}" width="300" />
</body>
</html>`;
}

Wenn wir diesen Code debuggen, würden wir sehen, dass der tatsächliche Wert für catGifSrc etwas wie Folgendes ist.

vscode-resource:/Users/toonces/projects/vscode-cat-coding/media/cat.gif

VS Code versteht diese spezielle URI und wird sie verwenden, um unser GIF von der Festplatte zu laden!

Standardmäßig können Webviews nur auf Ressourcen an folgenden Orten zugreifen:

  • Innerhalb des Installationsverzeichnisses Ihrer Erweiterung.
  • Innerhalb des aktuell aktiven Arbeitsbereichs des Benutzers.

Verwenden Sie WebviewOptions.localResourceRoots, um den Zugriff auf zusätzliche lokale Ressourcen zu ermöglichen.

Sie können auch jederzeit Data-URIs verwenden, um Ressourcen direkt in das Webview einzubetten.

Zugriff auf lokale Ressourcen steuern

Webviews können steuern, welche Ressourcen von der Festplatte des Benutzers geladen werden können, mit der Option localResourceRoots. localResourceRoots definiert eine Menge von Stamm-URIs, von denen lokale Inhalte geladen werden können.

Wir können localResourceRoots verwenden, um Cat Coding-Webviews auf das Laden von Ressourcen aus einem media-Verzeichnis in unserer Erweiterung zu beschränken.

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {
          // Only allow the webview to access resources in our extension's media directory
          localResourceRoots: [vscode.Uri.joinPath(context.extensionUri, 'media')]
        }
      );

      const onDiskPath = vscode.Uri.joinPath(context.extensionUri, 'media', 'cat.gif');
      const catGifSrc = panel.webview.asWebviewUri(onDiskPath);

      panel.webview.html = getWebviewContent(catGifSrc);
    })
  );
}

Um alle lokalen Ressourcen zu verbieten, setzen Sie localResourceRoots einfach auf [].

Im Allgemeinen sollten Webviews so restriktiv wie möglich beim Laden lokaler Ressourcen sein. Bedenken Sie jedoch, dass localResourceRoots allein keinen vollständigen Sicherheitsschutz bietet. Stellen Sie sicher, dass Ihr Webview auch die Sicherheitsbest-Practices befolgt und fügen Sie eine Content Security Policy hinzu, um die Inhalte, die geladen werden können, weiter einzuschränken.

Theming von Webview-Inhalt

Webviews können CSS verwenden, um ihr Erscheinungsbild basierend auf dem aktuellen Thema von VS Code zu ändern. VS Code gruppiert Themen in drei Kategorien und fügt dem body-Element eine spezielle Klasse hinzu, um das aktuelle Thema anzuzeigen.

  • vscode-light - Helle Themen.
  • vscode-dark - Dunkle Themen.
  • vscode-high-contrast - Hochkontrast-Themen.

Das folgende CSS ändert die Textfarbe des Webviews basierend auf dem aktuellen Thema des Benutzers.

body.vscode-light {
  color: black;
}

body.vscode-dark {
  color: white;
}

body.vscode-high-contrast {
  color: red;
}

Entwickeln Sie bei der Entwicklung einer Webview-Anwendung sicher, dass sie für die drei Arten von Themen funktioniert. Testen Sie Ihr Webview immer im Hochkontrastmodus, um sicherzustellen, dass es für Menschen mit visuellen Einschränkungen nutzbar ist.

Webviews können auch auf VS Code-Themenfarben über CSS-Variablen zugreifen. Diese Variablennamen sind mit vscode präfigiert und ersetzen den . durch -. Zum Beispiel wird editor.foreground zu var(--vscode-editor-foreground).

code {
  color: var(--vscode-editor-foreground);
}

Sehen Sie sich die Referenz zu Theme-Farben für die verfügbaren Theme-Variablen an. Eine Erweiterung ist verfügbar, die IntelliSense-Vorschläge für die Variablen bietet.

Die folgenden schriftartbezogenen Variablen sind ebenfalls definiert.

  • --vscode-editor-font-family - Editor-Schriftfamilie (aus der Einstellung editor.fontFamily).
  • --vscode-editor-font-weight - Editor-Schriftgewicht (aus der Einstellung editor.fontWeight).
  • --vscode-editor-font-size - Editor-Schriftgröße (aus der Einstellung editor.fontSize).

Schließlich sind für spezielle Fälle, in denen Sie CSS schreiben müssen, das auf ein einzelnes Thema abzielt, im body-Element von Webviews ein Datenattribut namens vscode-theme-id vorhanden, das die ID des aktuell aktiven Themas speichert. Dies ermöglicht es Ihnen, themenspezifisches CSS für Webviews zu schreiben.

body[data-vscode-theme-id="One Dark Pro"] {
    background: hotpink;
}

Unterstützte Medienformate

Webviews unterstützen Audio und Video, jedoch sind nicht alle Medien-Codecs oder Medientyp-Container unterstützt.

Die folgenden Audioformate können in Webviews verwendet werden:

  • Wav
  • Mp3
  • Ogg
  • Flac

Die folgenden Videoformate können in Webviews verwendet werden:

  • H.264
  • VP8

Für Videodateien stellen Sie sicher, dass sowohl das Video- als auch das Audioformat unterstützt werden. Viele .mp4-Dateien verwenden beispielsweise H.264 für Video und AAC für Audio. VS Code kann den Videoteil der mp4-Datei abspielen, aber da AAC-Audio nicht unterstützt wird, gibt es keinen Ton. Stattdessen müssen Sie mp3 für die Audiospur verwenden.

Kontextmenüs

Fortgeschrittene Webviews können das Kontextmenü anpassen, das angezeigt wird, wenn ein Benutzer innerhalb eines Webviews mit der rechten Maustaste klickt. Dies geschieht über einen Contribution Point ähnlich wie bei den normalen Kontextmenüs von VS Code, sodass benutzerdefinierte Menüs perfekt in den Rest des Editors passen. Webviews können auch benutzerdefinierte Kontextmenüs für verschiedene Bereiche des Webviews anzeigen.

Um einen neuen Kontextmenüeintrag zu Ihrem Webview hinzuzufügen, fügen Sie zuerst einen neuen Eintrag in menus unter dem neuen Abschnitt webview/context hinzu. Jeder Beitrag nimmt einen command (der auch der Titel des Elements ist) und eine when-Klausel. Die when-Klausel sollte webviewId == 'YOUR_WEBVIEW_VIEW_TYPE' enthalten, um sicherzustellen, dass die Kontextmenüs nur auf die Webviews Ihrer Erweiterung angewendet werden.

"contributes": {
  "menus": {
    "webview/context": [
      {
        "command": "catCoding.yarn",
        "when": "webviewId == 'catCoding'"
      },
      {
        "command": "catCoding.insertLion",
        "when": "webviewId == 'catCoding' && webviewSection == 'editor'"
      }
    ]
  },
  "commands": [
    {
      "command": "catCoding.yarn",
      "title": "Yarn 🧶",
      "category": "Cat Coding"
    },
    {
      "command": "catCoding.insertLion",
      "title": "Insert 🦁",
      "category": "Cat Coding"
    },
    ...
  ]
}

Innerhalb des Webviews können Sie auch die Kontexte für bestimmte Bereiche des HTML mit dem data-vscode-context Datenattribut (oder in JavaScript mit dataset.vscodeContext) festlegen. Der Wert von data-vscode-context ist ein JSON-Objekt, das die Kontexte angibt, die gesetzt werden, wenn der Benutzer auf das Element klickt. Der endgültige Kontext wird ermittelt, indem vom Dokument-Root zum angeklickten Element gegangen wird.

Betrachten Sie zum Beispiel dieses HTML:

<div class="main" data-vscode-context='{"webviewSection": "main", "mouseCount": 4}'>
  <h1>Cat Coding</h1>

  <textarea data-vscode-context='{"webviewSection": "editor", "preventDefaultContextMenuItems": true}'></textarea>
</div>

Wenn der Benutzer mit der rechten Maustaste auf das textarea klickt, werden die folgenden Kontexte gesetzt:

  • webviewSection == 'editor' - Dies überschreibt webviewSection vom Elternelement.
  • mouseCount == 4 - Dies wird vom Elternelement geerbt.
  • preventDefaultContextMenuItems == true - Dies ist ein spezieller Kontext, der die Kopieren- und Einfügen-Einträge ausblendet, die VS Code normalerweise zu Webview-Kontextmenüs hinzufügt.

Wenn der Benutzer mit der rechten Maustaste in den <textarea> klickt, sieht er:

Custom context menus showing in a webview

Manchmal kann es nützlich sein, ein Menü bei einem Linksklick/Primärklick anzuzeigen. Zum Beispiel, um ein Menü bei einem Split-Button anzuzeigen. Sie können dies tun, indem Sie das contextmenu-Ereignis in einem onClick-Ereignis auslösen.

<button data-vscode-context='{"preventDefaultContextMenuItems": true }' onClick='((e) => {
        e.preventDefault();
        e.target.dispatchEvent(new MouseEvent("contextmenu", { bubbles: true, clientX: e.clientX, clientY: e.clientY }));
        e.stopPropagation();
    })(event)'>Create</button>

Split button with a menu

Skripte und Message Passing

Webviews sind wie iframes, was bedeutet, dass sie auch Skripte ausführen können. JavaScript ist in Webviews standardmäßig deaktiviert, kann aber leicht wieder aktiviert werden, indem die Option enableScripts: true übergeben wird.

Verwenden wir ein Skript, um einen Zähler hinzuzufügen, der die von unserer Katze geschriebenen Quellcodezeilen verfolgt. Das Ausführen eines einfachen Skripts ist ziemlich einfach, aber beachten Sie, dass dieses Beispiel nur zu Demonstrationszwecken dient. In der Praxis sollte Ihr Webview immer Inline-Skripte mit einer Content Security Policy deaktivieren.

import * as path from 'path';
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {
          // Enable scripts in the webview
          enableScripts: true
        }
      );

      panel.webview.html = getWebviewContent();
    })
  );
}

function getWebviewContent() {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width="300" />
    <h1 id="lines-of-code-counter">0</h1>

    <script>
        const counter = document.getElementById('lines-of-code-counter');

        let count = 0;
        setInterval(() => {
            counter.textContent = count++;
        }, 100);
    </script>
</body>
</html>`;
}

A script running in a webview

Wow! Das ist eine produktive Katze.

Webview-Skripte können fast alles tun, was ein Skript auf einer normalen Webseite kann. Beachten Sie jedoch, dass Webviews in ihrem eigenen Kontext existieren, sodass Skripte in einem Webview keinen Zugriff auf die VS Code API haben. Dort kommt Message Passing ins Spiel!

Nachrichten von einer Erweiterung an ein Webview senden

Eine Erweiterung kann Daten an ihre Webviews senden, indem sie webview.postMessage() verwendet. Diese Methode sendet alle JSON-serialisierbaren Daten an das Webview. Die Nachricht wird im Webview über das Standardereignis message empfangen.

Um dies zu demonstrieren, fügen wir Cat Coding einen neuen Befehl hinzu, der die aktuell tippende Katze anweist, ihren Code zu refaktorieren (wodurch die Gesamtzahl der Zeilen reduziert wird). Der neue Befehl catCoding.doRefactor verwendet postMessage, um die Anweisung an das aktuelle Webview zu senden, und window.addEventListener('message', event => { ... }) innerhalb des Webviews selbst, um die Nachricht zu verarbeiten.

export function activate(context: vscode.ExtensionContext) {
  // Only allow a single Cat Coder
  let currentPanel: vscode.WebviewPanel | undefined = undefined;

  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      if (currentPanel) {
        currentPanel.reveal(vscode.ViewColumn.One);
      } else {
        currentPanel = vscode.window.createWebviewPanel(
          'catCoding',
          'Cat Coding',
          vscode.ViewColumn.One,
          {
            enableScripts: true
          }
        );
        currentPanel.webview.html = getWebviewContent();
        currentPanel.onDidDispose(
          () => {
            currentPanel = undefined;
          },
          undefined,
          context.subscriptions
        );
      }
    })
  );

  // Our new command
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.doRefactor', () => {
      if (!currentPanel) {
        return;
      }

      // Send a message to our webview.
      // You can send any JSON serializable data.
      currentPanel.webview.postMessage({ command: 'refactor' });
    })
  );
}

function getWebviewContent() {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width="300" />
    <h1 id="lines-of-code-counter">0</h1>

    <script>
        const counter = document.getElementById('lines-of-code-counter');

        let count = 0;
        setInterval(() => {
            counter.textContent = count++;
        }, 100);

        // Handle the message inside the webview
        window.addEventListener('message', event => {

            const message = event.data; // The JSON data our extension sent

            switch (message.command) {
                case 'refactor':
                    count = Math.ceil(count * 0.5);
                    counter.textContent = count;
                    break;
            }
        });
    </script>
</body>
</html>`;
}

Passing messages to a webview

Nachrichten von einem Webview an eine Erweiterung senden

Webviews können auch Nachrichten zurück an ihre Erweiterung senden. Dies geschieht über eine postMessage-Funktion auf einem speziellen VS Code API-Objekt innerhalb des Webviews. Um auf das VS Code API-Objekt zuzugreifen, rufen Sie acquireVsCodeApi innerhalb des Webviews auf. Diese Funktion kann nur einmal pro Sitzung aufgerufen werden. Sie müssen die Instanz der VS Code API, die von dieser Methode zurückgegeben wird, festhalten und an alle anderen Funktionen weitergeben, die sie verwenden müssen.

Wir können die VS Code API und postMessage in unserem Cat Coding-Webview verwenden, um die Erweiterung zu benachrichtigen, wenn unsere Katze einen Fehler in ihrem Code einführt.

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {
          enableScripts: true
        }
      );

      panel.webview.html = getWebviewContent();

      // Handle messages from the webview
      panel.webview.onDidReceiveMessage(
        message => {
          switch (message.command) {
            case 'alert':
              vscode.window.showErrorMessage(message.text);
              return;
          }
        },
        undefined,
        context.subscriptions
      );
    })
  );
}

function getWebviewContent() {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width="300" />
    <h1 id="lines-of-code-counter">0</h1>

    <script>
        (function() {
            const vscode = acquireVsCodeApi();
            const counter = document.getElementById('lines-of-code-counter');

            let count = 0;
            setInterval(() => {
                counter.textContent = count++;

                // Alert the extension when our cat introduces a bug
                if (Math.random() < 0.001 * count) {
                    vscode.postMessage({
                        command: 'alert',
                        text: '🐛  on line ' + count
                    })
                }
            }, 100);
        }())
    </script>
</body>
</html>`;
}

Passing messages from the webview to the main extension

Aus Sicherheitsgründen müssen Sie das VS Code API-Objekt privat halten und sicherstellen, dass es niemals in den globalen Geltungsbereich gelangt.

Web Worker verwenden

Web Worker werden innerhalb von Webviews unterstützt, es gibt jedoch einige wichtige Einschränkungen zu beachten.

Erstens können Worker nur über eine data:- oder blob:-URI geladen werden. Sie können keinen Worker direkt aus dem Verzeichnis Ihrer Erweiterung laden.

Wenn Sie Worker-Code aus einer JavaScript-Datei in Ihrer Erweiterung laden müssen, versuchen Sie es mit fetch.

const workerSource = 'absolute/path/to/worker.js';

fetch(workerSource)
  .then(result => result.blob())
  .then(blob => {
    const blobUrl = URL.createObjectURL(blob);
    new Worker(blobUrl);
  });

Worker-Skripte unterstützen auch nicht das Importieren von Quellcode über importScripts oder import(...). Wenn Ihr Worker Code dynamisch lädt, versuchen Sie, einen Bundler wie webpack zu verwenden, um das Worker-Skript in eine einzige Datei zu packen.

Mit webpack können Sie LimitChunkCountPlugin verwenden, um den kompilierten Worker-JavaScript zu einer einzelnen Datei zu erzwingen.

const path = require('path');
const webpack = require('webpack');

module.exports = {
  target: 'webworker',
  entry: './worker/src/index.js',
  output: {
    filename: 'worker.js',
    path: path.resolve(__dirname, 'media')
  },
  plugins: [
    new webpack.optimize.LimitChunkCountPlugin({
      maxChunks: 1
    })
  ]
};

Sicherheit

Wie bei jeder Webseite müssen Sie auch bei der Erstellung eines Webviews einige grundlegende Sicherheitsbest-Practices befolgen.

Fähigkeiten einschränken

Ein Webview sollte die minimale Anzahl von Fähigkeiten haben, die es benötigt. Wenn Ihr Webview beispielsweise keine Skripte ausführen muss, setzen Sie enableScripts: true nicht. Wenn Ihr Webview keine Ressourcen aus dem Arbeitsbereich des Benutzers laden muss, setzen Sie localResourceRoots auf [vscode.Uri.file(extensionContext.extensionPath)] oder sogar [], um den Zugriff auf alle lokalen Ressourcen zu verweigern.

Content Security Policy

Content Security Policies schränken die Inhalte, die in Webviews geladen und ausgeführt werden können, weiter ein. Eine Content Security Policy kann beispielsweise sicherstellen, dass nur eine Liste erlaubter Skripte im Webview ausgeführt werden kann, oder dem Webview sogar mitteilen, dass nur Bilder über https geladen werden sollen.

Um eine Content Security Policy hinzuzufügen, fügen Sie eine <meta http-equiv="Content-Security-Policy">-Direktive am Anfang des <head>-Elements des Webviews ein.

function getWebviewContent() {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <meta http-equiv="Content-Security-Policy" content="default-src 'none';">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Cat Coding</title>
</head>
<body>
    ...
</body>
</html>`;
}

Die Richtlinie default-src 'none'; verbietet alle Inhalte. Wir können dann die minimale Menge an Inhalt, die unsere Erweiterung benötigt, wieder aktivieren. Hier ist eine Content Security Policy, die das Laden lokaler Skripte und Stylesheets ermöglicht und Bilder über https lädt.

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'none'; img-src ${webview.cspSource} https:; script-src ${webview.cspSource}; style-src ${webview.cspSource};"
/>

Der Wert ${webview.cspSource} ist ein Platzhalter für einen Wert, der vom Webview-Objekt selbst stammt. Sehen Sie sich das Webview-Beispiel für ein vollständiges Beispiel an, wie dieser Wert verwendet wird.

Diese Content Security Policy deaktiviert auch implizit Inline-Skripte und -Stile. Es ist eine bewährte Methode, alle Inline-Stile und Skripte in externe Dateien zu extrahieren, damit sie ordnungsgemäß geladen werden können, ohne die Content Security Policy zu lockern.

Inhalte nur über HTTPS laden

Wenn Ihr Webview das Laden externer Ressourcen erlaubt, wird dringend empfohlen, nur zu erlauben, dass diese Ressourcen über https und nicht über http geladen werden. Die obige Beispiel-Content-Security-Policy tut dies bereits, indem sie nur erlaubt, dass Bilder über https: geladen werden.

Alle Benutzereingaben bereinigen

Genau wie bei einer normalen Webseite müssen Sie beim Erstellen von HTML für ein Webview alle Benutzereingaben bereinigen. Wenn Sie Eingaben nicht richtig bereinigen, können Injektionen von Inhalten auftreten, die Ihre Benutzer einem Sicherheitsrisiko aussetzen können.

Beispielwerte, die bereinigt werden müssen

  • Dateiinhalt.
  • Datei- und Ordnerpfade.
  • Benutzer- und Arbeitsbereichseinstellungen.

Ziehen Sie die Verwendung einer Hilfsbibliothek in Betracht, um Ihre HTML-Strings zu erstellen, oder stellen Sie zumindest sicher, dass alle Inhalte aus dem Arbeitsbereich des Benutzers ordnungsgemäß bereinigt werden.

Verlassen Sie sich niemals allein auf die Bereinigung für die Sicherheit. Stellen Sie sicher, dass Sie die anderen Sicherheitsbest-Practices befolgen, wie z. B. eine Content Security Policy, um die Auswirkungen möglicher Inhaltsinjektionen zu minimieren.

Persistenz

Im Standard-Webview- Lebenszyklus werden Webviews durch createWebviewPanel erstellt und zerstört, wenn der Benutzer sie schließt oder wenn .dispose() aufgerufen wird. Die Inhalte von Webviews werden jedoch erstellt, wenn das Webview sichtbar wird, und zerstört, wenn das Webview in den Hintergrund verschoben wird. Jeder Zustand innerhalb des Webviews geht verloren, wenn das Webview in einen Hintergrund-Tab verschoben wird.

Der beste Weg, dieses Problem zu lösen, ist, Ihr Webview zustandslos zu machen. Verwenden Sie Message Passing, um den Zustand des Webviews zu speichern und den Zustand wiederherzustellen, wenn das Webview wieder sichtbar wird.

getState und setState

Skripte, die innerhalb eines Webviews ausgeführt werden, können die Methoden getState und setState verwenden, um ein JSON-serialisierbares Zustandsobjekt zu speichern und wiederherzustellen. Dieser Zustand bleibt erhalten, auch nachdem der Webview-Inhalt selbst zerstört wurde, wenn ein Webview-Panel ausgeblendet wird. Der Zustand wird zerstört, wenn das Webview-Panel zerstört wird.

// Inside a webview script
const vscode = acquireVsCodeApi();

const counter = document.getElementById('lines-of-code-counter');

// Check if we have an old state to restore from
const previousState = vscode.getState();
let count = previousState ? previousState.count : 0;
counter.textContent = count;

setInterval(() => {
  counter.textContent = count++;
  // Update the saved state
  vscode.setState({ count });
}, 100);

getState und setState sind die bevorzugte Methode zur Persistenz von Zuständen, da sie einen wesentlich geringeren Performance-Overhead als retainContextWhenHidden haben.

Serialisierung

Durch die Implementierung eines WebviewPanelSerializer können Ihre Webviews automatisch wiederhergestellt werden, wenn VS Code neu gestartet wird. Die Serialisierung baut auf getState und setState auf und wird nur aktiviert, wenn Ihre Erweiterung einen WebviewPanelSerializer für Ihre Webviews registriert.

Damit unsere Coding Cats über VS Code-Neustarts hinweg erhalten bleiben, fügen Sie zuerst ein onWebviewPanel-Aktivierungsereignis zur package.json der Erweiterung hinzu.

"activationEvents": [
    ...,
    "onWebviewPanel:catCoding"
]

Dieses Aktivierungsereignis stellt sicher, dass unsere Erweiterung aktiviert wird, wann immer VS Code ein Webview mit dem ViewType: catCoding wiederherstellen muss.

Rufen Sie dann in der activate-Methode unserer Erweiterung registerWebviewPanelSerializer auf, um einen neuen WebviewPanelSerializer zu registrieren. Der WebviewPanelSerializer ist für die Wiederherstellung des Inhalts des Webviews aus seinem persistenten Zustand verantwortlich. Dieser Zustand ist das JSON-Objekt, das die Webview-Inhalte mit setState gesetzt haben.

export function activate(context: vscode.ExtensionContext) {
  // Normal setup...

  // And make sure we register a serializer for our webview type
  vscode.window.registerWebviewPanelSerializer('catCoding', new CatCodingSerializer());
}

class CatCodingSerializer implements vscode.WebviewPanelSerializer {
  async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: any) {
    // `state` is the state persisted using `setState` inside the webview
    console.log(`Got state: ${state}`);

    // Restore the content of our webview.
    //
    // Make sure we hold on to the `webviewPanel` passed in here and
    // also restore any event listeners we need on it.
    webviewPanel.webview.html = getWebviewContent();
  }
}

Wenn Sie nun VS Code mit einem geöffneten Cat Coding-Panel neu starten, wird das Panel automatisch an derselben Editor-Position wiederhergestellt.

retainContextWhenHidden

Für Webviews mit sehr komplexer UI oder Zuständen, die nicht schnell gespeichert und wiederhergestellt werden können, können Sie stattdessen die Option retainContextWhenHidden verwenden. Diese Option bewirkt, dass ein Webview seinen Inhalt beibehält, jedoch in einem versteckten Zustand, auch wenn das Webview selbst nicht mehr im Vordergrund ist.

Obwohl Cat Coding kaum als komplexer Zustand bezeichnet werden kann, versuchen wir, retainContextWhenHidden zu aktivieren, um zu sehen, wie sich die Option auf das Verhalten eines Webviews auswirkt.

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('catCoding.start', () => {
      const panel = vscode.window.createWebviewPanel(
        'catCoding',
        'Cat Coding',
        vscode.ViewColumn.One,
        {
          enableScripts: true,
          retainContextWhenHidden: true
        }
      );
      panel.webview.html = getWebviewContent();
    })
  );
}

function getWebviewContent() {
  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
</head>
<body>
    <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width="300" />
    <h1 id="lines-of-code-counter">0</h1>

    <script>
        const counter = document.getElementById('lines-of-code-counter');

        let count = 0;
        setInterval(() => {
            counter.textContent = count++;
        }, 100);
    </script>
</body>
</html>`;
}

retainContextWhenHidden demo

Beachten Sie, wie der Zähler nicht zurückgesetzt wird, wenn das Webview ausgeblendet und dann wiederhergestellt wird. Kein zusätzlicher Code erforderlich! Mit retainContextWhenHidden verhält sich das Webview ähnlich wie ein Hintergrund-Tab in einem Webbrowser. Skripte und andere dynamische Inhalte laufen weiter, auch wenn der Tab nicht aktiv oder sichtbar ist. Sie können auch Nachrichten an ein verstecktes Webview senden, wenn retainContextWhenHidden aktiviert ist.

Obwohl retainContextWhenHidden ansprechend sein mag, bedenken Sie, dass dies einen hohen Speicherbedarf hat und nur verwendet werden sollte, wenn andere Persistenztechniken nicht funktionieren.

Barrierefreiheit

Die Klasse vscode-using-screen-reader wird dem Haupt-Body Ihres Webviews in Kontexten hinzugefügt, in denen der Benutzer VS Code mit einem Screenreader bedient. Zusätzlich wird die Klasse vscode-reduce-motion dem Haupt-Body-Element des Dokuments hinzugefügt, wenn der Benutzer eine Präferenz zum Reduzieren der Bewegungsunschärfe im Fenster geäußert hat. Durch Beobachtung dieser Klassen und Anpassung Ihres Renderings entsprechend kann Ihr Webview-Inhalt die Präferenzen des Benutzers besser widerspiegeln.

Nächste Schritte

Wenn Sie mehr über die Erweiterbarkeit von VS Code erfahren möchten, probieren Sie diese Themen aus:

© . This site is unofficial and not affiliated with Microsoft.