有没有一种方法可以使VSCode扩展Webview中的安装按钮起作用?

时间:2020-10-16 19:30:33

标签: visual-studio-code webview vscode-extensions

我们正在gatsby.js上进行VSCode扩展,并且我们有一个树形视图,单击该树形视图将显示一个Webview。在Web视图中,我们有一个“安装按钮”,我们希望通过将命令发送到终端来使其运行“ npm install pluginName”。

我们在名为“ installPlugin”的类中有一个方法,该方法通过npm API解析以获取插件数据,例如npm install plugin命令。

对于Webview内容,我们使用panel.webview.html添加html字符串。在button标记上,我们具有一个onclick属性,该属性的值是installPlugin函数的调用。但是,单击该按钮时不执行任何操作。相反,当单击树视图中的插件(同时打开Web视图时)时,将运行npm install命令。

某些类中installPlugin方法的代码如下:

/* ---------- Logic handling the installation of Plugins and Themes --------- */

  async installPlugin(plugin?: any): Promise<void> {
    const activeTerminal = Utilities.getActiveTerminal();
    const gatsbyIsInitiated:
      | boolean
      | null = await Utilities.checkIfGatsbySiteInitiated();

    if (!gatsbyIsInitiated) {
      const input = await window.showErrorMessage(
        'Open up a new workspace containing only the site you are working on.',
        'Change Workspace',
        'Cancel'
      );
      if (input && input === 'Change Workspace') {
        commands.executeCommand('vscode.openFolder');
      }
      return;
    }
    // const rootPath = await Utilities.getRootPath();
    const { name, links } = plugin.command.arguments[0];
    if (plugin) {
      const installCmnd =
        (await PluginData.getNpmInstall(links.repository, links.homepage)) ||
        `npm install ${name}`;

      // if (rootPath) {
      //   activeTerminal.sendText(`cd && cd ${rootPath}`);
      //   activeTerminal.sendText(installCmnd);
      //   activeTerminal.show(true);
      // } else {
      // }
      activeTerminal.sendText(installCmnd);
      activeTerminal.show(true);
      // check for if "plugin" is a theme or actual plugin
      if (name.startsWith('gatsby-theme')) {
        window.showInformationMessage(
          'Refer to this theme\'s documentation regarding implementation. Simply click on the theme in the "Themes" section.',
          'OK'
        );
      } else {
        window.showInformationMessage(
          'Refer to this plugin\'s documentation regarding further configuration. Simply click on the plugin in the "Plugins" section.',
          'OK'
        );
      }
    }
  }

webview面板的代码在这里:

export default class WebViews {
  static async openWebView(npmPackage: any) {
    // const { links, name, version, description } = npmPackage;
    const readMe = await PluginData.mdToHtml(links.repository, links.homepage);

    // turn npm package name from snake-case to standard capitalized title
    const title = name
      .replace(/-/g, ' ')
      .replace(/^\w?|\s\w?/g, (match: string) => match.toUpperCase());

    // createWebviewPanel takes in the type of the webview panel & Title of the panel & showOptions
    const panel = window.createWebviewPanel(
      'plugin',
      `Gatsby Plugin: ${title}`,
      ViewColumn.One
    );

    // create a header for each npm package and display README underneath header
    // currently #install-btn does not work
    panel.webview.html = `
    <style>
      .plugin-header {
        position: fixed;
        top: 0;
        background-color: var(--vscode-editor-background);
        width: 100vw;
      }

      #title-btn {
        display: flex;
        flex-direction: row;
        align-items: center;
        align-text: center;
      }

      #install-btn {
        height: 1.5rem;
        margin: 1rem;
      }

      body {
        position: absolute;
        top: 9rem;
      }
    </style>
    <div class="plugin-header">
      <div id="title-btn">
        <h1 id="title">${title}</h1>
        <button id="install-btn" onclick="${installPlugin(npmPackage)}">Install</button>
      </div>
      <p>Version: ${version}</p>
      <p>${description}</p>
      <hr class="solid">
    </div>
    ${readMe}
    `;

    // close the webview when not looking at it
    panel.onDidChangeViewState((e) => {
      if (!e.webviewPanel.active) {
        panel.dispose();
      }
    });
  }

总而言之,我们想知道是否有一种方法可以使webview.panel.html中的onclick属性具有对类中的方法(即installPlugin方法)的引用。似乎webview中的html没有对installPlugin方法的引用。

1 个答案:

答案 0 :(得分:0)

最重要的是,您不能从扩展名中调用Web视图中的代码,反之亦然!内化之后,事情对您来说应该变得更加明显。

您要做的是发送消息,就像您与Web Worker一样。您的按钮只能触发Webview代码中的功能。并且此函数应该向vscode发送一条消息。反过来,这最终会出现在您的扩展程序Webview中。有关更多详细信息,请参见webview documentation,尤其是message passing paragraph