XML 声明中的 NativeScript 全局事件处理程序

NativeScript global event handler in an XML declaration?

本文关键字:全局 事件处理 程序 NativeScript 声明 XML      更新时间:2023-09-26

所以我试图弄清楚这是否可能与NativeScript一起使用。

所以我知道,为了能够在XML声明中添加事件处理程序,您必须在javascript文件中定义一个函数,如下所示(主页.js):

exports.testAlert = function(){
    alert('test alert');
}

然后我可以在XML文件(主页.xml)中使用:

<Button tap="testAlert" text="testAlert" height="50px" style="font-size:20px;" />

问题是我无法在另一个页面(内部页面.xml)中全局使用"testAlert"功能。

最初,我尝试使用全局对象并在应用程序.js文件中声明我希望全局的函数,如下所示:

global.testAlert = function(){
    alert('test alert');
}

我首先认为我可以像以前一样访问 XML 中的函数:

<Button tap="testAlert" text="testAlert" height="50px" style="font-size:20px;" />

这不起作用,所以我想可能是这样的(global.testAlert):

<Button tap="global.testAlert" text="testAlert" height="50px" style="font-size:20px;" />

但是为了拥有相同的函数,我需要在 inside-page.js 文件中再次创建它,或者至少将全局函数链接到本地函数,如下所示:

exports.testAlert = global.testAlert;

是否可以在单个 JS 文件中创建可在任何 XML 页面中使用的事件处理程序?可能保存在应用程序.js文件中?

或者,如果所有全局函数都像全局函数一样在自己的文件中.js那么包含在我需要它的地方?

除此之外,我知道您还可以在 JS 文件中添加事件处理程序。现在我不介意这种方法,如果它在全球范围内有效?

因此,最终我希望能够创建全局函数和变量,然后可以在应用程序中的任何位置使用它们。

任何帮助将不胜感激。

我当前的解决方案:

所以我现在找到了一个解决方法,它并不理想,但它对我有用。

我首先在应用程序中创建了一个对象(global.toolbox.js以保留我所有的函数和变量:

// This is just a technique I stumbled across to avoid UNDEFINED errors
// Should be placed at the top of each JS file
global.toolbox = global.toolbox || {};

我将全局对象定义为正常:

global.toolbox = global.toolbox || {};
global.toolbox.testFunction = function(){
    alert('test alert');
}

然后要在其他页面中访问这些全局函数,我确实需要添加一个小片段来"导出"XML文件可以访问的全局函数,这将在主页中.js例如:

global.toolbox = global.toolbox || {};
for (var k in global.toolbox){
    if (global.toolbox.hasOwnProperty(k)) {
         exports[k] = global.toolbox[k];
    }
}

我把它放在每个XML文件的每个JS文件的顶部。

现在我能够访问 XML 文件中的全局函数:

<Button tap="testFunction" text="testFunction" height="50px" style="font-size:20px;" />

我仍然想看看是否有办法避免将代码片段添加到每个 JS 文件中并为 XML 声明制作真正的全局函数。

希望这对某人有所帮助。

我找到了一些解决方法来满足您的需求。看这里:https://github.com/NativeScript/NativeScript/issues/2860

我试图完成类似的事情,并找到了一个不明显但有效且更简单的解决方案。

步骤 1:将所需的函数添加到应用程序资源中。

例如,在应用程序根目录中.js:

const application = require("application");
...
Object.assign(application.getResources(), {
    testAlert(message) {
        return function(args) {
            dialogs.alert(message);
        }
    },
    testAlertWithPredefinedMessage() {
        return function(args) {
            dialogs.alert('This alert message was predefined');
        }
    },
    whateverOtherGloballyAvailableHandlerYouWant(whatever, args, you, want) {
        return function(args) {
            // Here, put whatever you want this event handler to do.
            // Note the one limitation:  None of the arguments can be function declarations, nor lambdas.  However, strings, numbers, booleans, etc, all work.
        }
    }
};

步骤 2:在 XML 中,使用绑定语法和括号:

<Button text="Tap me!" onTap="{{ testAlert('Thank you for tapping!') }}" />
<Button text="Note that the parentheses are still required, even if there are no arguments to pass in" onTap="{{ testAlertWithPredefinedMessage() }}" />

不明显,但简单,高效。


奖励:假设你想做一些更复杂的事情,并且仍然在XML中尽可能多地做这些事情。 例如,假设您要定义一个函数或 lambda,将其作为参数传递给其他函数,并且您希望在 XML 中执行此操作。

警告:如果你不想使用eval,或者觉得eval总是邪恶的,请停止阅读,堵住你的耳朵,唱"啦啦啦",同时我快速解释一些技巧。

奖励步骤1:制作一个"真正邪恶"的eval,它总是在最全球化的范围内运行。

const geval = eval; // "geval" stands for "global eval", but if you want, you could call it "gevil" or such like instead.

奖励步骤 2:将这些全局事件处理程序添加到应用程序资源:

Object.assign(application.getResources(), {
    geval(expression) {
        return function(args) {
            geval(expression);
        }
    },
    gevalProp(propertyName) { // The reason for this will be more evident shortly.
        return function(args) {
            geval(args.object[propertyName]);
        }
    }
};

奖励步骤3:现在将任意代码直接放在XML中,作为geval的字符串参数:

<Button text="Tap me!" onTap="{{ geval('dialogs.alert(`Thank you geval!`)') }}" />

但是,如果您密切关注,您会注意到该代码表达式中唯一可用于未转义使用的 javascript 字符串分隔符是反引号。 根据您要完成的任务,这可能就足够了,或者可能令人沮丧,或者可能是不可行的限制。

输入(鼓声)gevalProp。 它允许您将要计算的表达式存储在单独的属性中,这允许您释放其他两个可用的字符串分隔符之一,以便在表达式中用于计算。 例如

<Button text="Tap me!" onTap="{{ gevalProp('onTapExpr') }}" onTapExpr="dialogs.alert('Thank you gevalProp!')" />

当然,你可能在意识形态或风格上不喜欢这个,这很好 - 在这种情况下忽略这个"奖金"部分 - 但对于那些希望突破界限并知道什么是可能的,这是可能的。