【问题标题】:NativeScript global event handler in an XML declaration?XML 声明中的 NativeScript 全局事件处理程序?
【发布时间】:2016-04-26 02:04:27
【问题描述】:

所以我想弄清楚 NativeScript 是否可以做到这一点。

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

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

然后我可以在 XML 文件中使用它(ma​​in-page.xml):

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

问题是我无法在另一个页面(inside-page.xml)中全局使用“testAlert”功能。

最初,我尝试使用全局对象并在 app.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 页面的事件处理程序?可能保存在 app.js 文件中?

或者如果所有的全局函数都在它自己的文件中,比如 global-functions.js 然后包含在我需要的地方?

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

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

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript android xml nativescript


    【解决方案1】:

    我目前的解决方案:

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

    我首先在 app.js 中创建了一个对象(global.toolbox)来保存我所有的函数和变量:

    // 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');
    }
    

    然后要在其他页面访问这些全局函数,我确实需要添加一点 sn-p 来“导出”XML 文件可以访问的全局函数,这将在 ma​​in-page.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;" />
    

    我仍然想看看是否有办法避免将 sn-p 添加到每个 JS 文件并为 XML 声明创建真正的全局函数。

    希望这对某人有所帮助。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        第 1 步:将您想要的功能添加到应用程序资源中。

        例如在 app-root.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:进行“真正邪恶”的评估,始终在最全局范围内运行。

        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!')" />
        

        当然,你可能在思想上或风格上不喜欢这个,这很好 - 在这种情况下忽略这个“奖励”部分 - 但对于那些希望突破界限并知道什么是可能的人来说,这是可能的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-07-21
          • 1970-01-01
          • 2021-11-05
          • 2023-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多