212

我在 AngularJS 中缓存局部有问题。

在我的 HTML 页面中,我有:

<body>
 <div ng-view></div>
<body>

我的部分加载的地方。

当我更改部分 HTML 代码时,浏览器仍会加载旧数据。

有什么解决方法吗?

4

12 回答 12

201

对于开发,您还可以停用浏览器缓存 - 在 Chrome Dev Tools 的右下角单击齿轮并勾选选项

禁用缓存(在 DevTools 打开时)

更新:在 Firefox 中,调试器 -> 设置 -> 高级部分有相同的选项(检查版本 33)

更新 2:虽然此选项出现在 Firefox 中,但一些报告称它不起作用。我建议使用萤火虫并遵循 hadaytullah 的回答。

于 2013-10-04T08:49:34.660 回答
112

以@Valentyn 的回答为基础,这是一种在 ng-view 内容更改时始终自动清除缓存的方法:

myApp.run(function($rootScope, $templateCache) {
   $rootScope.$on('$viewContentLoaded', function() {
      $templateCache.removeAll();
   });
});
于 2013-02-06T04:06:12.677 回答
38

如其他答案中所述,herehere,可以使用以下方法清除缓存:

$templateCache.removeAll();

但是,正如gatoatigrado评论中所建议的那样,这仅在没有任何缓存标头的情况下提供 html 模板时才有效。

所以这对我有用:

在角度:

app.run(['$templateCache', function ( $templateCache ) {
    $templateCache.removeAll(); }]);

您可能会以多种方式添加缓存标头,但这里有一些对我有用的解决方案。

如果使用IIS,请将其添加到您的 web.config 中:

<location path="scripts/app/views">
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="DisableCache" />
    </staticContent>
  </system.webServer>
</location>

如果使用 Nginx,您可以将其添加到您的配置中:

location ^~ /scripts/app/views/ {
    expires -1;   
}

编辑

我刚刚意识到问题提到了dev机器,但希望这仍然可以帮助某人......

于 2014-03-12T17:24:03.843 回答
31

如果您谈论的是用于缓存模板而不重新加载整个页面的缓存,那么您可以通过以下方式清空它:

.controller('mainCtrl', function($scope, $templateCache) {
  $scope.clearCache = function() { 
    $templateCache.removeAll();
  }
});

在标记中:

<button ng-click='clearCache()'>Clear cache</button>

并按此按钮清除缓存。

于 2013-02-05T23:57:03.693 回答
22

使用 Firebug (22.0.6) 的 Firefox (33.1.1) 解决方案

  1. 工具 > Web 工具 > Firebug > 打开 Firebug。
  2. 在 Firebug 视图中,转到“Net”视图。
  3. “网络”(视图的标题)旁边将出现一个下拉菜单符号。
  4. 从下拉菜单中选择“禁用浏览器缓存”。
于 2014-11-22T23:27:08.550 回答
19

这个片段帮助我摆脱了模板缓存

app.run(function($rootScope, $templateCache) {
    $rootScope.$on('$routeChangeStart', function(event, next, current) {
        if (typeof(current) !== 'undefined'){
            $templateCache.remove(current.templateUrl);
        }
    });
});

以下片段的详细信息可以在此链接上找到:http: //oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/

于 2014-05-03T06:51:24.103 回答
16

我发布这个只是为了涵盖所有可能性,因为其他解决方案都不适合我(它们由于 angular-bootstrap 模板依赖性等而引发错误)。

在开发/调试特定模板时,可以通过在路径中包含时间戳来确保它始终刷新,如下所示:

       $modal.open({
          // TODO: Only while dev/debug. Remove later.
          templateUrl: 'core/admin/organizations/modal-selector/modal-selector.html?nd=' + Date.now(),
          controller : function ($scope, $modalInstance) {
            $scope.ok = function () {
              $modalInstance.close();
            };
          }
        });

注意变量?nd=' + Date.now()中的final 。templateUrl

于 2015-01-28T16:31:47.377 回答
11

正如其他人所说,完全出于开发目的而取消缓存可以在不更改代码的情况下轻松完成:使用浏览器设置或插件。在开发人员之外,要击败基于路由的模板的 Angular 模板缓存,请在 $routeChangeStart(或 $stateChangeStart,对于 UI 路由器)期间从缓存中删除模板 URL,如 Shayan 所示。但是,这不会影响 ng-include 加载的模板的缓存,因为这些模板不是通过路由器加载的。

我希望能够在生产中修补任何模板,包括那些由 ng-include 加载的模板,并让用户在浏览器中快速接收修补程序,而无需重新加载整个页面。我也不担心破坏模板的 HTTP 缓存。解决方案是拦截应用程序发出的每个 HTTP 请求,忽略那些不适用于我的应用程序的 .html 模板的请求,然后将参数添加到每分钟更改一次的模板 URL。请注意,路径检查特定于应用程序模板的路径。要获得不同的间隔,请更改参数的数学运算,或完全删除 % 以获得不缓存。

// this defeats Angular's $templateCache on a 1-minute interval
// as a side-effect it also defeats HTTP (browser) caching
angular.module('myApp').config(function($httpProvider, ...) {
    $httpProvider.interceptors.push(function() {
        return {
            'request': function(config) {
                config.url = getTimeVersionedUrl(config.url);
                return config;
            }
        };
    });

    function getTimeVersionedUrl(url) {
        // only do for html templates of this app
        // NOTE: the path to test for is app dependent!
        if (!url || url.indexOf('a/app/') < 0 || url.indexOf('.html') < 0) return url;
        // create a URL param that changes every minute
        // and add it intelligently to the template's previous url
        var param = 'v=' + ~~(Date.now() / 60000) % 10000; // 4 unique digits every minute
        if (url.indexOf('?') > 0) {
            if (url.indexOf('v=') > 0) return url.replace(/v=[0-9](4)/, param);
            return url + '&' + param;
        }
        return url + '?' + param;
    }
于 2015-05-15T19:20:00.360 回答
8

如果您使用的是 UI 路由器,那么您可以使用装饰器并更新 $templateFactory 服务并将查询字符串参数附加到 templateUrl,浏览器将始终从服务器加载新模板。

function configureTemplateFactory($provide) {
    // Set a suffix outside the decorator function 
    var cacheBust = Date.now().toString();

    function templateFactoryDecorator($delegate) {
        var fromUrl = angular.bind($delegate, $delegate.fromUrl);
        $delegate.fromUrl = function (url, params) {
            if (url !== null && angular.isDefined(url) && angular.isString(url)) {
                url += (url.indexOf("?") === -1 ? "?" : "&");
                url += "v=" + cacheBust;
            }

            return fromUrl(url, params);
        };

        return $delegate;
    }

    $provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}

app.config(['$provide', configureTemplateFactory]);

我相信你可以通过修饰 $routeProvider 中的“when”方法来达到同样的效果。

于 2014-12-14T05:26:21.713 回答
3

我发现 HTTP 拦截器方法工作得非常好,并且允许额外的灵活性和控制。此外,您可以使用发布哈希作为 buster 变量来缓存每个生产版本。

下面是 dev cachebusting 方法使用的样子Date

app.factory('cachebustInjector', function(conf) {   
    var cachebustInjector = {
        request: function(config) {    
            // new timestamp will be appended to each new partial .html request to prevent caching in a dev environment               
            var buster = new Date().getTime();

            if (config.url.indexOf('static/angular_templates') > -1) {
                config.url += ['?v=', buster].join('');
            }
            return config;
        }
    };
    return cachebustInjector;
});

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('cachebustInjector');
}]);
于 2017-03-24T16:55:36.793 回答
1

这是 Chrome 中的另一个选项。

点击F12打开开发者工具。然后Resources > Cache Storage > Refresh Caches

在此处输入图像描述

我喜欢这个选项,因为我不必像其他答案那样禁用缓存。

于 2015-08-28T13:52:04.270 回答
0

没有解决方案可以防止浏览器/代理缓存,因为您无法控制它。

另一种向用户强制提供新鲜内容的方法是重命名 HTML 文件!就像https://www.npmjs.com/package/grunt-filerev对资产所做的一样。

于 2015-03-03T15:11:26.007 回答