Google 应用程序脚本 (V8);为什么我不能在 onOpen 中使用对象实例?

Google Apps Script (V8); why can't I use an object instance inside of onOpen?

为什么我不能在 onOpen 中使用对象实例?

我正在使用新的 V8 运行time 试验 Google Apps 脚本。我写了一些简单的代码,在 onOpen 函数中创建了一个 class 的实例,并尝试在我单击菜单项时关联对该实例的方法的调用。

当我单击关联的菜单项时,出现 "Script function not found" 错误。但是,当我创建 class 的全局实例或在另一个函数中创建本地实例时,它工作正常。

我尝试记录本地实例或全局实例的值,但它只显示一个空对象:{}.

这是一个错误,还是我在阅读文档时遗漏了一些细节?

/** Application Class */
class Application {
    /**
     * ShowUi
     */
    showUi() {
        // const html = HtmlService.createHtmlOutputFromFile('Ui');
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        const ui = SpreadsheetApp.getUi();
        ui.showModalDialog(html, 'User Interface');
    }
}

const global_app = new Application();

/** onOpen */
function onOpen() {
    const app = new Application();
    const ui = SpreadsheetApp.getUi();
    const menu = ui.createMenu('JSClass Example');

    console.log('app, local scope:');
    console.log(app);

    console.log('app, global scope');
    console.log(global_app);

    menu.addItem('Show UI (local)', 'app.showUi');
    menu.addItem('Show UI (global)', 'global_app.showUi');
    menu.addItem('Show UI (global fn)', 'showUi');

    menu.addToUi();
}

/** showUi */
function showUi() {
    const app3 = new Application();
    app3.showUi();
}

我为此代码绑定的电子表格是 here。不过,我认为您必须制作一个副本并单击一些看起来很吓人的警告才能真正 运行 它。

我使用了一个可安装的 onOpen 触发器,但它也适用于一个简单的触发器。我第一次 运行 时没有注意菜单。

/** Application Class */
class Application {
    /**
     * ShowUi
     */
    showUi() {
        // const html = HtmlService.createHtmlOutputFromFile('Ui');
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        SpreadsheetApp.getUi().showModalDialog(html, 'User Interface');
    }
}

const global_app = new Application();

/** onOpen */
function openForMe() {
    const app = new Application();
    const ui = SpreadsheetApp.getUi();
    const menu = ui.createMenu('JSClass Example')
    .addItem('Show UI (local)', 'app.showUi')//this is still not working
    .addItem('Show UI (global)', 'global_app.showUi')
    .addItem('Show UI (global fn)', 'showUi')
    .addToUi();
}

/** showUi */
function showUi() {
    const app3 = new Application();
    app3.showUi();
}

这似乎还可以:

/** Application Class */
class Application {
     showUi() {
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        SpreadsheetApp.getUi().showModalDialog(html, 'User Interface');
    }
}

const global_app = new Application();

/** onOpen */
function onOpen(){
  SpreadsheetApp.getUi().createMenu('JSClass Example')
  .addItem('Show UI (global)', 'global_app.showUi')
  .addItem('Show UI (global fn)', 'showUi')
  .addToUi();
}

/** showUi */
function showUi() {
    const app3 = new Application();
    app3.showUi();
}

在您的示例中,仅执行 onOpen() 方法来填充菜单,但在 selected 菜单选项时不会执行。

当您 select 一个菜单项时,它是在新的执行上下文中执行的,并且不会保留上一次执行(即填充菜单)的 onOpen() 函数内的状态.


另一种方法是使用 static method,您无需创建 class 的实例即可调用它。

class Application {
    static showUi() {
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        const ui = SpreadsheetApp.getUi();
        ui.showModalDialog(html, 'User Interface');
    }
}

function onOpen() {
    const app = new Application();
    const ui = SpreadsheetApp.getUi();
    const menu = ui.createMenu('V8 Menu Test');
    menu.addItem('Show UI', 'Application.showUi');
    menu.addToUi();
}