【问题标题】:How to detect browser using angularjs?如何使用angularjs检测浏览器?
【发布时间】:2018-10-12 18:55:29
【问题描述】:

我是 angularjs 的新手。如何在 angularjs 中检测 userAgent。是否可以在控制器中使用它?尝试了类似下面的方法,但没有运气!

  var browserVersion = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);

我需要专门检测IE9!

【问题讨论】:

  • 我认为这里的问题是为什么您要使用角度检测浏览器吗?是否有您想要嗅探的特定功能
  • 不能为 OP 说话;这个问题描述了导致 me 到这个相关问题的需求:(stackoverflow.com/questions/16098430/…)。本质上 IE 执行积极的缓存;我不知道可以对此进行检查的 Modernizr 风格功能。
  • 我检测浏览器的具体情况是,如果开发者控制台关闭,IE 不会检测到localStorage(事件storage)的变化。我还不知道为什么。因此,当使用“真实”浏览器时,我依赖于 storage 事件,但在 IE 的情况下,我必须使用 interval 定期检查 localStorage

标签: angularjs angularjs-directive angularjs-scope angular-ui


【解决方案1】:

就像 Eliran Malka 所问的那样,为什么需要检查 IE 9?

检测浏览器的品牌和版本通常很糟糕。这通常意味着如果您需要 JavaScript 来检测特定版本的浏览器,则代码存在更大的问题。

确实存在某些功能不起作用的情况,例如 IE 8 或 9 不支持 WebSockets。这应该通过检查 WebSocket 支持来解决,如果没有原生支持,则应用 polyfill。

这应该通过像 Modernizr 这样的库来完成。

话虽如此,您可以轻松创建返回浏览器的服务。在某些情况下,浏览器中存在功能但实现已过时或损坏。 Modernizr 不适用于这些情况。

app.service('browser', ['$window', function($window) {

     return function() {

         var userAgent = $window.navigator.userAgent;

        var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i};

        for(var key in browsers) {
            if (browsers[key].test(userAgent)) {
                return key;
            }
       };

       return 'unknown';
    }

}]);

修正了错字浏览器

注意:这只是一个示例,说明如何在 Angular 中创建将嗅探 userAgent 字符串的服务。这只是一个代码示例,预计不会在生产环境中工作并报告所有情况下的所有浏览器。

更新

最好使用像https://github.com/ded/bowserhttps://github.com/darcyclarke/Detect.js 这样的第三方库。这些库分别在名为 bowser 或 detect 的 window 上放置一个对象。

然后您可以像这样向Angular IoC Container 公开它:

angular.module('yourModule').value('bowser', bowser);

或者

detectFactory.$inject = ['$window'];
function detectFactory($window) {
    return detect.parse($window.navigator.userAgent);
} 
angular.module('yourModule').factory('detect', detectFactory);

然后,您会以通常的方式注入其中一种,并使用 lib 提供的 API。如果您选择使用另一个使用构造函数方法的库,您将创建一个实例化它的工厂:

function someLibFactory() {
    return new SomeLib();
}
angular.module('yourModule').factory('someLib', someLibFactory);

然后,您可以以正常方式将其注入您的控制器和服务中。

如果您要注入的库与您的要求不完全匹配,您可能需要使用Adapter Pattern,您可以在其中使用您需要的确切方法创建一个类/构造函数。

在这个例子中,我们只需要测试 IE 9,我们将使用上面的 bowser 库。

BrowserAdapter.$inject = ['bowser']; // bring in lib
function BrowserAdapter(bowser) {
    this.bowser = bowser;
}

BrowserAdapter.prototype.isIe9 = function() {
    return this.bowser.msie && this.browser.version == 9;
}

angular.module('yourModule').service('browserAdapter', BrowserAdapter);

现在在控制器或服务中,您可以注入 browserAdapter 并执行 if (browserAdapter.isIe9) { // do something }

如果稍后您想使用检测而不是 bowser,则代码中的更改将被隔离到 BrowserAdapter。

更新

实际上,这些值永远不会改变。如果您在 IE 9 中加载页面,它将永远不会成为 Chrome 44。因此,不要将 BrowserAdapter 注册为服务,只需将结果放入 valueconstant

angular.module('app').value('isIe9', broswerAdapter.isIe9);

【讨论】:

  • forEach 中的错字:broswers,替换为 browsers
  • 另外两个问题: 1. angular.forEach() 循环不起作用,因为它只是循环遍历每个项目。最好使用老式的 for...in 构造。 2. 正则表达式 /internet explorer/i 不会检测到 IE 11,而是将其报告为 Chrome,请参阅 stackoverflow.com/questions/17907445/how-to-detect-ie11 搜索 /trident/i 我相信适用于与 Angular 兼容的所有 IE 版本。现在。
  • 有时浏览器会以不同的行为实现相同的功能(例如,占位符在焦点或键下隐藏)。所以你必须走这条路
  • 最新版本的 Chrome 报告了这一点:“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36”。因此,根据您的 forEach 语句检索键的顺序,它可以返回不同的结果。
  • “检测浏览器的品牌和版本通常很糟糕。”不,当您认为在 100 次中检测浏览器版本 99 的目的是针对 Internet Explorer 的可憎性时,它不会。在我 6 年的 Web 开发中,我只需要这个功能是因为 Internet Explorer,因为 IE 从 1995 年起就伪装成 Mozilla,这表明这是 Microsoft 的错,而不是 Web 开发人员的错。
【解决方案2】:

Angular 库使用document.documentMode 来识别 IE。它包含 IE 的主要版本号,如果用户代理不是 IE,则为 NaN/undefined。

/**
* documentMode is an IE-only property
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
*/
var msie = document.documentMode;

https://github.com/angular/angular.js/blob/v1.5.0/src/Angular.js#L167-L171

$document 示例(window.document 的角度包装器)

// var msie = document.documentMode;
var msie = $document[0].documentMode;
// if is IE (documentMode contains IE version)
if (msie) {
  // IE logic here

  if (msie === 9) {
    // IE 9 logic here

  }
}

【讨论】:

  • 有几次我在 window.navigator 等上进行正则表达式测试时遇到大而复杂的答案。当我们只想击败 IE 时,这似乎是最好的方法。
【解决方案3】:

你应该使用条件 cmets

<!--[if IE 9]>
<script type="text/javascript">
    window.isIE9 = true;
</script>
<![endif]-->

然后您可以在控制器中检查 $window.isIE9。

【讨论】:

  • OP说:我需要专门检测IE9!
【解决方案4】:

不知道为什么你指定它必须在 Angular 中。它很容易通过 JavaScript 完成。查看navigator 对象。

只需打开您的控制台并检查navigator。看来您要特别寻找的是.userAgent.appVersion

我没有安装IE9,但是你可以试试下面的代码

//Detect if IE 9
if(navigator.appVersion.indexOf("MSIE 9.")!=-1)

【讨论】:

  • 如果您安装了 IE10 或 IE11,您可以使用 IE 的 F12 功能将其呈现为 IE9。
【解决方案5】:

您可以轻松使用“ng-device-detector”模块。

https://github.com/srfrnk/ng-device-detector

var app = angular.module('myapp', ["ng.deviceDetector"]);
app.controller('DeviceCtrl', ["$scope","deviceDetector",function($scope,deviceDetector) {
      console.log("browser: ", deviceDetector.browser);
      console.log("browser version: ", deviceDetector.browser_version);
      console.log("device: ", deviceDetector.device);
}]);

【讨论】:

    【解决方案6】:

    因此,您可以通过创建包含内容的文件来为 Angular 声明更多实用程序(我遵循 RGraph 库)

    (function(window, angular, undefined) {'use strict';
        var agl = angular || {};
        var ua  = navigator.userAgent;
    
        agl.ISFF     = ua.indexOf('Firefox') != -1;
        agl.ISOPERA  = ua.indexOf('Opera') != -1;
        agl.ISCHROME = ua.indexOf('Chrome') != -1;
        agl.ISSAFARI = ua.indexOf('Safari') != -1 && !agl.ISCHROME;
        agl.ISWEBKIT = ua.indexOf('WebKit') != -1;
    
        agl.ISIE   = ua.indexOf('Trident') > 0 || navigator.userAgent.indexOf('MSIE') > 0;
        agl.ISIE6  = ua.indexOf('MSIE 6') > 0;
        agl.ISIE7  = ua.indexOf('MSIE 7') > 0;
        agl.ISIE8  = ua.indexOf('MSIE 8') > 0;
        agl.ISIE9  = ua.indexOf('MSIE 9') > 0;
        agl.ISIE10 = ua.indexOf('MSIE 10') > 0;
        agl.ISOLD  = agl.ISIE6 || agl.ISIE7 || agl.ISIE8; // MUST be here
    
        agl.ISIE11UP = ua.indexOf('MSIE') == -1 && ua.indexOf('Trident') > 0;
        agl.ISIE10UP = agl.ISIE10 || agl.ISIE11UP;
        agl.ISIE9UP  = agl.ISIE9 || agl.ISIE10UP;
    
    })(window, window.angular);
    

    之后,在你的函数中可以像这样使用它

    function SampleController($scope){
        $scope.click = function () {
            if(angular.ISCHROME) {
            alert("is chrome");
        }
    }
    

    【讨论】:

    • 为我工作。谢谢!
    • 猴子修补角度被认为是一种不好的做法。
    • 是的,马丁,我们可以用另一个变量代替 window.angular。不需要window.angular
    【解决方案7】:

    我修改了上述技术,该技术与我想要的角度技术接近,并将其转变为服务:-)。我包含 ie9 是因为我在 angularjs 应用程序中遇到了一些问题,但可能是我正在做的事情,所以请随时将其取出。

    angular.module('myModule').service('browserDetectionService', function() {
    
     return {
    isCompatible: function () {
    
      var browserInfo = navigator.userAgent;
      var browserFlags =  {};
    
      browserFlags.ISFF = browserInfo.indexOf('Firefox') != -1;
      browserFlags.ISOPERA = browserInfo.indexOf('Opera') != -1;
      browserFlags.ISCHROME = browserInfo.indexOf('Chrome') != -1;
      browserFlags.ISSAFARI = browserInfo.indexOf('Safari') != -1 && !browserFlags.ISCHROME;
      browserFlags.ISWEBKIT = browserInfo.indexOf('WebKit') != -1;
    
      browserFlags.ISIE = browserInfo.indexOf('Trident') > 0 || navigator.userAgent.indexOf('MSIE') > 0;
      browserFlags.ISIE6 = browserInfo.indexOf('MSIE 6') > 0;
      browserFlags.ISIE7 = browserInfo.indexOf('MSIE 7') > 0;
      browserFlags.ISIE8 = browserInfo.indexOf('MSIE 8') > 0;
      browserFlags.ISIE9 = browserInfo.indexOf('MSIE 9') > 0;
      browserFlags.ISIE10 = browserInfo.indexOf('MSIE 10') > 0;
      browserFlags.ISOLD = browserFlags.ISIE6 || browserFlags.ISIE7 || browserFlags.ISIE8 || browserFlags.ISIE9; // MUST be here
    
      browserFlags.ISIE11UP = browserInfo.indexOf('MSIE') == -1 && browserInfo.indexOf('Trident') > 0;
      browserFlags.ISIE10UP = browserFlags.ISIE10 || browserFlags.ISIE11UP;
      browserFlags.ISIE9UP = browserFlags.ISIE9 || browserFlags.ISIE10UP;
    
      return !browserFlags.ISOLD;
      }
    };
    
    });
    

    【讨论】:

      【解决方案8】:

      有一个库 ng-device-detector 可以轻松检测浏览器等实体。

      这里是解释如何使用这个库的教程。 Detect OS, browser and device in AngularJS

      ngDeviceDetector

      您需要将 re-tree.js 和 ng-device-detector.js 脚本添加到您的 html 中

      在您的模块中注入“ng.deviceDetector”作为依赖项。

      然后将库提供的“deviceDetector”服务注入您的控制器或工厂,无论您需要数据的任何地方。

      “deviceDetector”包含有关浏览器、操作系统和设备的所有数据。

      【讨论】:

        【解决方案9】:

        为什么不用document.documentMode 只能在IE下使用:

        var doc = $window.document;
        if (!!doc.documentMode)
        {
          if (doc.documentMode === 10)
          {
            doc.documentElement.className += ' isIE isIE10';
          }
          else if (doc.documentMode === 11)
          {
            doc.documentElement.className += ' isIE isIE11';
          }
          // etc.
        }
        

        【讨论】:

        • 对不起,可能是 Bohdan 的重复答案,但有一些额外的......
        • 或 $document[0] 代替 $window.document
        【解决方案10】:

        通常应避免浏览器嗅探,特征检测要好得多,但有时您必须这样做。例如,在我的情况下,Windows 8 Tablets 用软键盘覆盖了浏览器窗口;我知道这很荒谬,但有时你必须面对现实。

        因此,您可以像使用常规 JavaScript 一样测量“navigator.userAgent”(请不要养成将 Angular 视为与 JavaScript 不同的东西的习惯,尽可能使用纯 JavaScript,这样会减少未来的重构)。

        但是,对于测试,您希望使用注入对象而不是全局对象。由于'$location' 不包含userAgent,简单的技巧是使用'$window.location.userAgent'。您现在可以编写测试,使用您不想模拟的任何 userAgent 注入 $window 存根。

        我已经很多年没有使用它了,但是 Modernizr 是一个很好的检查功能的代码源。 https://github.com/Modernizr/Modernizr/issues/878#issuecomment-41448059

        【讨论】:

        • 嘿,谢谢你的分析器。能否请您提供代码 sn-p 或链接以供进一步阅读?
        【解决方案11】:

        检测ie9+

        var userAgent, ieReg, ie;
          userAgent = $window.navigator.userAgent;
          ieReg = /msie|Trident.*rv[ :]*11\./gi;
          ie = ieReg.test(userAgent);
        
        if (ie) {
           // js for ie9,10 and 11
        }
        

        【讨论】:

          猜你喜欢
          • 2018-06-19
          • 2017-02-09
          • 2011-09-08
          • 1970-01-01
          • 2011-10-13
          • 2013-11-12
          • 1970-01-01
          • 2011-03-10
          • 2013-10-21
          相关资源
          最近更新 更多