【问题标题】:Onsen UI broke my PayPal script (and all other javascript)Onsen UI 破坏了我的 PayPal 脚本(以及所有其他 javascript)
【发布时间】:2016-11-13 17:43:04
【问题描述】:

我一直在慢慢地将 Onsen UI 与我现有的网络应用程序集成。

我的主页文件 (index.jade) 包含一个拆分器,可以在整个应用程序中导航。拆分器加载一个 NodeJS 路由,该路由以翡翠呈现请求的页面。到目前为止,一切都按预期工作(实际上只是我所有的前端翡翠代码都被正确渲染)。拆分器的每一页都存储在一个单独的jade文件中(首页除外)。

问题:

通过以这种方式配置我的应用程序,我通过反复试验了解到,我所有的翡翠文件中的所有 javascript 都不再使用翡翠代码呈现(我不知道正确的术语)。如果我将它们剪切并粘贴到 index.jade,或者创建单独的 javascript 文件并将它们包含在 index.jade 中,我只能让我的 javascript 工作。

这本身就是一个问题(尽管我可以通过执行上述操作来解决它),但这是我的主要问题的原因:它破坏了我的一个页面上的我的 PayPal 脚本。

在集成 Onsen UI 之前,我在我的应用程序中成功使用了 PayPal 上下文结账。

代码示例:

这是我在开始集成 Onsen UI 之前在我的一个视图中实施 PayPal 的方式:

//- the following is for In-Context PayPal checkout ********************
  div(ng-show="viewEvent && viewEvent.spacesAvailable > 0")
    br
    label(ng-show='eventStatus === 1') This event is being hosted by you! You can not RSVP.  
    label(ng-show='eventStatus === 2') You have RSVP'd for this event, but have not payed.
    label(ng-show='eventStatus === 3') You have already payed for this event.
    label(ng-show='eventStatus === 4') RSVP
    form#myContainer(ng-show='eventStatus === 2 || eventStatus === 4' action="{{'https://10.0.0.25:8001/checkout/' + user._id + '/' + viewEvent._id + '/' + viewEvent.eventName + '/' + viewEvent.price}}" ng-click='rsvp(user._id, viewEvent._id);' method='get')
    script.
      window.paypalCheckoutReady = function () {
        paypal.checkout.setup("**redacted**", {
          environment: "sandbox",
          container: "myContainer"
        });
      };
    script(src='//www.paypalobjects.com/api/checkout.js', async)

我只是将脚本放在那里,所有内容都正确加载,并且我能够使用 PayPal 的非关联结账进行购买。 但是,现在我不能像那样插入脚本。我已将代码更改为:

//- the following is for In-Context PayPal checkout ********************
  div(ng-if="viewEvent && viewEvent.spacesAvailable > 0")
    br
    label(ng-show='eventStatus === 1') This event is being hosted by you! You can not RSVP.  
    label(ng-show='eventStatus === 2') You have RSVP'd for this event, but have not payed.
    label(ng-show='eventStatus === 3') You have already payed for this event.
    label(ng-show='eventStatus === 4') RSVP
    form#myContainer(ng-show='eventStatus === 2 || eventStatus === 4' action="{{'https://10.0.0.25:8001/checkout/' + user._id + '/' + viewEvent._id + '/' + viewEvent.eventName + '/' + viewEvent.price}}" ng-click='rsvp(user._id, viewEvent._id);' method='get')
    div(ng-init='openPayPal()')

最后一个 div 调用了 angular 控制器中的一个函数 openPayPal(),该函数调用了 index.jade 中包含的 javascript 文件中的一个函数:

function openPayPal() {
  window.paypalCheckoutReady = function () {
    paypal.checkout.setup("**redacted**", {
      environment: "sandbox",
      container: "myContainer"
    });
  };
}

此外,PayPal 脚本:

script(src='//www.paypalobjects.com/api/checkout.js', async)

现在包含在 index.jade 中。

所以在做完这一切之后,PayPal 按钮甚至都没有出现。我相信这是因为我在脚本上做错了。

我没有想法。

有谁知道如何实现这一点,或者知道我做错了什么?

另外,有人知道在我的玉文件中包含 javascript 的解决方法吗?

感谢大家的宝贵时间。

更新

如果我转到 index.jade,删除正文下方的所有内容(包括加载 PayPal 按钮不起作用的页面的拆分器),然后粘贴以下代码,然后 PayPal 按钮会按预期显示(就像我开始集成 Onsen UI 之前一样)。

form#myContainer(action='*deleted for now*' method='get')
script.
  window.paypalCheckoutReady = function () {
    paypal.checkout.setup("*redacted*", {
      environment: "sandbox",
      container: "myContainer"
    });
  };
script(src='//www.paypalobjects.com/api/checkout.js' async)

解决方案更新 2

我无法从我的控制器动态加载脚本。这是 search.jade 中的内容:

  //- the following is for In-Context PayPal checkout ********************
  div(ng-show="viewEvent && viewEvent.spacesAvailable > 0")
    br
    label(ng-show='eventStatus === 1') This event is being hosted by you! You can not RSVP.  
    label(ng-show='eventStatus === 2') You have RSVP'd for this event, but have not payed.
    label(ng-show='eventStatus === 3') You have already payed for this event.
    label(ng-show='eventStatus === 4') RSVP
    form#myContainer(on-load='controller.openPayPalPlease()' ng-show='eventStatus === 2 || eventStatus === 4' action="{{'https://10.0.0.25:8001/checkout/' + user._id + '/' + viewEvent._id + '/' + viewEvent.eventName + '/' + viewEvent.price}}" ng-click='rsvp(user._id, viewEvent._id);' method='get')

这是我在控制器中的角度函数:

this.openPayPalPlease = function() {
    window.paypalCheckoutReady = function () {
      paypal.checkout.setup("H6LX5CJXEQYEL", {
        environment: "sandbox",
        container: "myContainer"
      });
    };

    var s = document.createElement('script');
    s.setAttribute('src', '//www.paypalobjects.com/api/checkout.js');
    document.getElementById('myContainer').appendChild(s);
  };

请注意我是如何在翡翠文件的 PayPal 表单中使用 on-load 调用角度函数的。不使用 on-load,并将这个 div 放在 PayPal 表单下,

div(ng-init='controller.openPayPalPlease()')

我收到错误:

无法在 openPayPalPlease 读取属性 'appendChild' 的 null

使用 on-load,没有任何反应,脚本也不会被加载。

【问题讨论】:

  • 顺便说一句,因为其中一些问题会引起双方的大量讨论和更新,而不仅仅是一个问答,您可能有兴趣查看 onsen ui 社区论坛。 community.onsen.io
  • 你是对的。我想从现在开始我会在论坛上发布我的问题。

标签: javascript node.js express paypal onsen-ui


【解决方案1】:

我猜想由于某些情况,要么你没有正确调用你的函数,要么你试图在它准备好之前调用它。

旁注:虽然这可能不是问题 - 现在您正在调用全局函数 - 在 Angular 中,有两种常见的事件处理方法。

方式 1(旧但常见的方式)

module.controller('MyController', function($scope) {
    $scope.myHandler = function() { ... };
});

<div ng-controller="MyController">
    <div ng-event-name="myHandler()"></div>
</div>

方式 2(新,推荐)

module.controller('MyController', function() {
    this.myHandler = function() { ... };
});

<div ng-controller="MyController as MC">
    <div ng-event-name="MC.myHandler()"></div>
</div>

因此,您可以尝试使用其中一种方法。您还可以尝试在openPayPalpaypalCheckoutReady 函数中执行一些console.logs,以确保一切正常执行。此外,您应该检查控制台中是否出现任何错误。 (右键→检查元素→控制台)

更新

我检查了paypalobjects.com/api/checkout.js 的实现,我想我发现了发生了什么。

到目前为止,我一直期待您仍在调用您的 paypalCheckoutReady 函数,但实际上结帐脚本似乎会检查它是否存在并执行它,否则它会执行默认函数。由于您是定义函数的人,因此您实际上应该能够在其中添加 console.log 并看到它没有被执行。

既然您说您将 paypal 脚本移至 index.jade,这意味着它在您的实际代码执行之前很久就已执行。值得庆幸的是,如果您没有具有 data-paypal-(button|id|sandbox) 属性的元素,则调用的默认函数不会做任何事情,所以您很安全。

唯一剩下的就是调用你的函数。我检查了脚本的实现,所以它对你的函数所做的唯一事情就是在页面加载后调用它。因此,在您的情况下,您可以自己调用它。您可以在定义 paypalCheckoutReady 函数后添加这一行,如下所示:

window.paypal && window.paypalCheckoutReady();

或者,您可以从控制器动态加载贝宝脚本。从概念层面来看,这可能是一个优雅的解决方案,因为它通常为您提供对程序流程的更多控制。 所以像

var s = document.createElement('script');
s.setAttribute('src', '//www.paypalobjects.com/api/checkout.js');
parent.appendChild(s);

其中parentdocument.bodydocument.head、您的页面或您喜欢的任何内容。您还可以进行一些检查以防止再次加载脚本。

我认为这两种解决方案都应该有效,因此您可以使用您喜欢的一种。

【讨论】:

  • 感谢您的回答。使用方式 2,我能够让我的其余 javascript 以这种方式工作,而不是将其包含在单独的 js 文件中(我更喜欢这种方式,因为我现在可以在一个地方看到所有代码)。但是我的 PayPal 代码仍然损坏。我放了一个 console.log('here');最后如果 openPayPal(); (现在在我的角度文件中),它在控制台中正确打印,没有错误。所以我在以前的地方。
  • 然而,paypalCheckoutReady 来自我在本文第一段代码末尾包含的脚本。我相信这个脚本必须在表单代码的正下方,并像上面一样跟随脚本,才能正常工作。
  • 我还更新了我的帖子以包含更多信息。
  • 我还更新了我的答案 - 解决方案是手动调用您的函数或在定义函数后动态加载贝宝脚本。使用你喜欢的任何东西。
  • 感谢您的更新。我很高兴得知我可以像这样从控制器动态加载脚本,而且我肯定会在我的应用程序的其他部分使用它。但是,在这种情况下我很难做到这一点。你能在这篇文章中看到我的最新更新吗?
【解决方案2】:

PayPal 存在一个问题,如果 document.readyState == 'interactive' 则不会调用您的函数。您只需在调试控制台中输入document.readyState 即可验证这一点。

如果您的资源仍在加载,则可能会出现这种情况 - 但是我也相信当前版本的 Chrome 中存在错误,我正在尝试重现该错误以便报告。

检查 Chrome 调试工具的“网络”标签以查找任何长时间运行的请求。

我也向 PayPal 报告了这个问题,但他们通常没有希望,所以我不希望他们修复它。

我最终设置了 5 秒的超时,然后检查 window.paypal 是否已初始化,如果是,我只需自己调用我的初始化函数并设置一个布尔值以防止它再次发生。

【讨论】:

    猜你喜欢
    • 2013-11-27
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多