是否可以清除 Ionic 中的视图缓存?

IT技术 javascript ionic
2021-03-08 22:13:10

我目前正在处理一个 Angular/Ionic/Cordova 项目,我们最近升级到了最新的 Ionic 测试版。从项目之前使用的版本开始,这引入了视图缓存。然而,这样做也带来了一个问题。

该应用程序面向客户并且非常以数据为中心。但是,目前用户必须进行身份验证才能查看与其帐户关联的数据;当用户注销并登录到另一个帐户时,因为视图仍被缓存,它们会显示上一个帐户的视图。

当用户登录时,应用程序仍应缓存视图,因为它有助于使应用程序感觉更快,但应在用户注销时清除缓存。

设置cache-view="false"不是一个选项,因为它会完全禁用缓存。

我也试过设置$ionicConfig.views.maxCache(0);然后回到默认值 10,希望这样做可以清除缓存,但没有效果。

我能想到的最后一件事是在用户登录时触发一个事件,刷新当前加载到视图中的所有数据 - 但是,这将比我认为应该花费更多的努力。

有没有办法简单地清除视图缓存?

5个回答

在 app.js 中的状态定义中,您可以添加cache:false以禁用缓存(请参阅Ionic 文档中的禁用状态提供程序中的缓存。或者,您可以保持缓存,除非您知道数据已更改。

  • 如果你已经在页面上,你可以这样做, $state.go($state.currentState, {}, {reload:true})
  • 如果您处于另一个状态并且想要返回到通常缓存的状态但您希望它被刷新,您可以这样做, $ionicHistory.clearCache().then(function(){ $state.go('app.fooState') })

请注意,后者需要 clearCache 返回Promise。查看我在此拉取请求中所做的更改,并将您现在拥有的 clearCache 实现与我的进行比较:https : //github.com/driftyco/ionic/pull/3724

注意:此处的“后一种”解决方案会清除除当前处于活动状态的视图之外的所有视图如果您还想清除活动视图,一种解决方案是1.清除缓存,2.导航到要刷新的页面,3.再次清除缓存。例如$ionicHistory.clearCache().then(function() { $state.go('app.fooState').then(function() { $ionicHistory.clearCache() } })
2021-05-05 22:13:10
以防万一您的 ionic clearCache 函数不返回Promise,您可以随时将其包装如下: $q.when($ionicHistory.clearCache()).then(function(){ $state.go('app.fooState') })
2021-05-08 22:13:10
杰出的。“后一点”使我们的“切换帐户”用例变得非常简单。一行代码。太感谢了!
2021-05-19 22:13:10

我偶然发现了一个类似的场景,其中使用另一个用户登录时向我显示过时/缓存的视图。您可以cache: false在状态定义级别执行此操作,但这会在您的应用程序中完全禁用该状态的缓存。

当用户进入您的应用程序的登录/登录状态时,您可以做的是清除所有缓存的视图和历史记录(如您所说)。看起来很理想。

// code inside your signin controller

$scope.$on("$ionicView.enter", function () {
   $ionicHistory.clearCache();
   $ionicHistory.clearHistory();
});
我偶然发现了一个场景,在退出后登录时总是会出现一个白页。您的解决方案轻松修复了这个功能齐全的交互式白屏。
2021-05-11 22:13:10

您也可以通过cache:false在您的设置做到这一点$stateProvider

$stateProvider.state('myState', {
   cache: false,
   url : '/myUrl',
   templateUrl : 'my-template.html'
})

你在寻找这样的东西吗?:

$ionicHistory.clearCache();

编辑:

Ionic 的 github 中存在一个问题: Issue

嗯,这是一个老问题,我将解释真正发生的事情以及如何解决它:

PS:如果您想直接进入解决方案,请立即向下滚动。

$ionicHistory.clearCache() 的代码:

 `clearCache: function(stateIds) { return $timeout(function() { 
     $ionicNavViewDelegate._instances.forEach(function(instance) { 
         instance.clearCache(stateIds); 
     }); 
 }`

因此,如您所见,它需要 1 个参数 cllaed stateIds,它是一个 stateId 数组。事实上,我努力发现 stateId 只不过是 stateName。

所以,让我们更深入。在“instance.clearCache(stateIds)”上面一行中使用的 $ionicNavView.clearCache 的代码是:

self.clearCache = function(stateIds) {
var viewElements = $element.children();
var viewElement, viewScope, x, l, y, eleIdentifier;

for (x = 0, l = viewElements.length; x < l; x++) {
  viewElement = viewElements.eq(x);

  if (stateIds) {
    eleIdentifier = viewElement.data(DATA_ELE_IDENTIFIER);

    for (y = 0; y < stateIds.length; y++) {
      if (eleIdentifier === stateIds[y]) {
        $ionicViewSwitcher.destroyViewEle(viewElement);
      }
    }
    continue;
  }

  if (navViewAttr(viewElement) == VIEW_STATUS_CACHED) {
    $ionicViewSwitcher.destroyViewEle(viewElement);

  } else if (navViewAttr(viewElement) == VIEW_STATUS_ACTIVE) {
    viewScope = viewElement.scope();
    viewScope && viewScope.$broadcast('$ionicView.clearCache');
  }

}
};

正如您在代码中看到的,这个 clearCache 不会清除所有缓存,相反,它会销毁与 stateIds 数组中的值匹配的所有缓存视图。如果没有参数,它只会破坏实际视图。

因此,仅使用 Ionic 方式的解决方案是使用数组中的所有状态名称作为参数调用 $ionicHistory.clearCache() 。

例如:解决方案 $ionicHistory.clearCache(['login', 'map', 'home']); 我无法相信任何 Ionic 开发人员之前没有深入研究代码,或者错过了这个简单的数据。有很多人为此感到痛苦。

为了清楚起见,我想指出错误本身的位置(如果我们可以称之为错误),也许对开发人员来说很方便:

self.clearCache = 函数(stateIds){

[...]

 var viewElements = $element.children();

整个函数的作用基本上是:

使用 JQLite 获取所有元素 循环元素 检查 StateIds 数组中的元素是否等于 1 并销毁它;转到下一个元素。检查循环中的元素是否已缓存或处于活动状态,在两种真实情况下都将其销毁 不是所有视图内容的数组,甚至不是缓存的内容,无论是否有意,它都不会遍历所有状态以清除所有与“活动”或“缓存”匹配的状态。如果您希望它遍历所有状态并销毁所有缓存的视图和数据,则需要明确传递 stateIds 数组参数。

除此之外还有另一种奇怪的行为,因为当我调试它时,我看到 var viewElements 数组被 2 个元素填满,而这 2 个元素来自相同的状态,一个解析为 'CACHED' 另一个解析器为 'ACTIVE',甚至解析为 if 条件中使用的两种类型,缓存根本没有被清除。

我个人认为这是某种错误实施或被广泛错误使用。事实是,很多人对此嗤之以鼻,开发人员甚至没有给出这个简单的解释。