Cordova + Angularjs + 设备就绪

Posted

技术标签:

【中文标题】Cordova + Angularjs + 设备就绪【英文标题】:Cordova + Angularjs + Device Ready 【发布时间】:2014-02-28 15:14:27 【问题描述】:

我正在使用 Cordova 和 AngularJS 开发一个移动应用程序。如何在 Cordova 设备准备好之前限制 AngluarJS 的引导。基本上我不想在设备准备好之前使用任何 AngularJS 控制器。

【问题讨论】:

检查这个角度2解决方案也***.com/a/44397322/3600674 【参考方案1】:

手动引导您的 Angular 应用:

从您的 html 代码中删除您的 ng-app 属性,因此 Angular 不会自行启动。

javascript 代码中添加类似这样的内容:

document.addEventListener("deviceready", function() 
    // retrieve the DOM element that had the ng-app attribute
    var domElement = document.getElementById(...) / document.querySelector(...);
    angular.bootstrap(domElement, ["angularAppName"]);
, false);

bootstrapping 应用程序的 Angular 文档。

【讨论】:

设备就绪事件是否总是在文档就绪后触发?如果没有,有时这将不起作用 当应用程序在浏览器中运行时,如果没有 Cordova,这将不起作用。我下面的解决方案解决了这个问题。 请参阅下面我的回答,了解@olanod 的担忧。 @michaeloryl @wade-anderson 回答的window.ionic.Platform.ready() 怎么样?【参考方案2】:

我正在使用以下解决方案,它允许 AngularJS 在与 Cordova 一起运行时以及在直接在浏览器中运行时被引导,这是我的大部分开发工作发生的地方。您必须从主 index.html 页面中删除 ng-app 指令,因为这是手动引导正在取代的内容。

更新:我已经切换到以下方法,我认为它更清洁。它适用于 Ionic 以及 vanilla Cordova/PhoneGap。它应该是 JavaScript 的最后一点运行 - 可能在 /body 标记之前的 script 标记内。

  angular.element(document).ready(function () 
    if (window.cordova) 
      console.log("Running in Cordova, will bootstrap AngularJS once 'deviceready' event fires.");
      document.addEventListener('deviceready', function () 
        console.log("Deviceready event has fired, bootstrapping AngularJS.");
        angular.bootstrap(document.body, ['app']);
      , false);
     else 
      console.log("Running in browser, bootstrapping AngularJS now.");
      angular.bootstrap(document.body, ['app']);
    
  );

这是我使用的旧解决方案:

// This is a function that bootstraps AngularJS, which is called from later code
function bootstrapAngular() 
    console.log("Bootstrapping AngularJS");
    // This assumes your app is named "app" and is on the body tag: <body ng-app="app">
    // Change the selector from "body" to whatever you need
    var domElement = document.querySelector('body');
    // Change the application name from "app" if needed
    angular.bootstrap(domElement, ['app']);


// This is my preferred Cordova detection method, as it doesn't require updating.
if (document.URL.indexOf( 'http://' ) === -1 
        && document.URL.indexOf( 'https://' ) === -1) 
    console.log("URL: Running in Cordova/PhoneGap");
    document.addEventListener("deviceready", bootstrapAngular, false);
 else 
    console.log("URL: Running in browser");
    bootstrapAngular();

如果您在使用 http/https 检测方法时遇到问题,可能是因为从 Web 将 Cordova 应用程序加载到手机中,您可以改用以下方法:

function bootstrapAngular() 
    console.log("Bootstrapping AngularJS");
    // This assumes your app is named "app" and is on the body tag: <body ng-app="app">
    // Change the selector from "body" to whatever you need
    var domElement = document.querySelector('body');
    // Change the application name from "app" if needed
    angular.bootstrap(domElement, ['app']);


// This method of user agent detection also works, though it means you might have to maintain this UA list
if (navigator.userAgent.match(/(ios|iPhone|iPod|iPad|android|BlackBerry)/)) 
    console.log("UA: Running in Cordova/PhoneGap");
    document.addEventListener("deviceready", bootstrapAngular, false);
 else 
    console.log("UA: Running in browser");
    bootstrapAngular();

请注意,您仍然需要与第一个示例相同的 bootstrapAngular 函数。

为什么要使用 Cordova/PhoneGap/Ionic 手动引导 AngularJS?

有些人一开始可能不知道您为什么要这样做。问题是您可能拥有依赖于 Cordova/PhoneGap/Ionic 插件的 AngularJS 代码,而这些插件要等到 AngularJS 启动后才能准备好,因为 Cordova 在设备上启动和运行所需的时间比普通的旧 Javascript 代码要长对于 AngularJS 来说。

所以在这些情况下,我们必须等到 Cordova/PhoneGap/Ionic 准备好后才能启动(引导)AngularJS,以便 Angular 拥有运行所需的一切。

例如,假设您正在使用 NG-Persist Angular 模块,它利用本地存储在浏览器上保存数据,iOS Keychain plugin(在 iOS 上运行)和 cordova-plugin-file(在 Android 上运行)。如果您的 Angular 应用程序尝试立即加载/保存某些内容,NG-Persist 对 window.device.platform(来自 device plugin)的检查将失败,因为移动代码尚未完成启动,您将得到只不过是一个白页,而不是你漂亮的应用程序。

【讨论】:

为了能够在浏览器中进行测试,我通常会创建一个包含一些代码的虚假 cordova.js 文件,例如自动立即调用任何“deviceready”注册事件。 @user276648 你能分享你的假cordova.js(例如作为github gist)吗? 如果我这样做,我会得到“未捕获的错误:[$injector:modulerr] 无法实例化模块应用程序,原因是:错误:[$injector:nomod] 模块‘app’不可用!你要么拼错了模块名称,要么忘记加载它。如果注册模块,请确保将依赖项指定为第二个参数。”我能做什么? @KenVernaillen 我的猜测是您的主应用程序模块不像我的示例中那样称为app。查看angular.bootstrap(document.body, ['app']); 这两行并将其更改为您应用程序中的主模块的名称。如果它对您有用,请不要忘记投票...... @MichaelOryl Sir 这是否意味着我不再需要在我的个人插件调用中准备好设备?【参考方案3】:

如果您使用Ionic,此解决方案适用于浏览器和设备。在此 thread 上感谢 romgar。

window.ionic.Platform.ready(function() 
    angular.bootstrap(document, ['<your_main_app']);
);

仍然需要从 DOM 元素中删除 ng-app。

【讨论】:

这太棒了 这仅在您使用 Ionic 时有效(在撰写问题时不存在)。仍然有开发人员在没有 Ionic 的情况下使用 Cordova 和 Angular。 @TheHippo 谢谢先生。我错过了。我已经编辑了我的答案,以包括您使用 Ionic 的规定。 你能举一个完整的例子吗?我无法让它工作。这段代码在 angular.module.run、$ionicPlatform.ready 内部还是外部? @CarlosGoce 代码 sn-p 不应该在 Angular 中运行。它在您的 HTML 页面底部以纯 Javascript 执行。如果您的 HTML 中确实有 ng-app 属性,请记住不要删除它 - 它的功能被上面的 sn-p 引导 Angular 所取代【参考方案4】:

当我使用时,这个解决方案变得更加健壮:

angular.element(document).ready(function () 
  var domElement = document.getElementById('appElement');
  angular.bootstrap(domElement, ["angularAppName"]);
);

更新

我的建议是将上述内容放在适当的 deviceready 函数中,例如:

document.addEventListener("deviceready", function() 
    angular.element(document).ready(function () 
      var domElement = document.getElementById('appElement');
      angular.bootstrap(domElement, ["angularAppName"]);
    );
, false);

【讨论】:

documentReady != deviceready 如果您在代码的早期使用任何特定于 Cordova 的函数,则这些函数可能还没有准备好。 这应该在 deviceready 处理程序中,并取自引导文档。 另外,如果你在 HTML 元素之后包含你的 JavaScript,你不需要等到 DOM 完全加载。 我不明白反对意见。我的建议来自引导文档,完整的代码是(对我来说很好):document.addEventListener("deviceready", function() angular.element(document).ready(function () // retrieve the DOM element that had the ng-app attribute var domElement = document.getElementById('appElement'); angular.bootstrap(domElement, ["angularAppName"]); ); , false); 您能否详细说明为什么您说这更健壮? @TheHippo 的解决方案是否有时会为您失败?【参考方案5】:

关于使用 TheHippo 的解决方案:

document.addEventListener("deviceready", function() 
    // retrieve the DOM element that had the ng-app attribute
    var domElement = document.getElementById(...) / document.querySelector(...);
    angular.bootstrap(domElement, ["angularAppName"]);
, false);

它在浏览器中不起作用,因为“cordova.js”由 Cordova 或 Phonegap 构建过程解析,并且在您的本地主机或模拟测试环境中不可用。

因此永远不会触发“deviceready”事件。您可以简单地在浏览器控制台中手动触发它。

var customDeviceReadyEvent = new Event('deviceready');
document.dispatchEvent(customDeviceReadyEvent);

还要确保在设置所有 Angular 模块/控制器/工厂/指令等后触发 Angular 的引导程序。

【讨论】:

【参考方案6】:

在大多数情况下,您可能不需要在 deviceready 之前阻止加载您的 Angular 应用程序(请注意,如果您有很多插件,deviceready 可能需要几秒钟才能触发)。

相反,您可以使用类似这个库 (https://github.com/arnesson/angular-cordova) 的东西,它通过自动缓冲调用为您解决 deviceready 问题,然后在 deviceready 被触发后执行它们。

【讨论】:

以上是关于Cordova + Angularjs + 设备就绪的主要内容,如果未能解决你的问题,请参考以下文章

我想利用ionic,cordova,angularjs来制作一个简单的app应用,想知道具体该如何开始,能在浏览器测试就好

ngCordova插件安装使用

ionic 和cordova的区别是啥

邮政研究基于Ionic+AngularJS+Cordova框架的异常邮件双录查据系统手机客户端的构建(节选)

如果 gps 暂时不可用,Cordova 地理定位插件无法正常工作

ionic+cordova+angularJs