我目前正在开展Angular / Ionic / Cordova项目,我们最近已升级到最新的Ionic beta版。从项目之前使用的版本开始,这引入了视图缓存。然而,它也引入了一个问题。
该应用程序面向客户,并且非常以数据为中心。但是,用户必须进行身份验证才能查看与其帐户关联的数据;当用户注销并登录到另一个帐户时,由于视图仍然被缓存,因此会显示最后一个帐户的视图。
应用程序仍然应该在用户登录时缓存视图,因为它有助于让应用程序感觉更快,但是当用户注销时应该清除缓存。
设置cache-view="false"
不是一个选项,因为它会完全禁用缓存。
我还尝试设置$ionicConfig.views.maxCache(0);
然后回到默认值10,希望它会清除缓存这样做,但它没有效果。
我能想到的最后一件事是在用户登录时触发一个事件,刷新当前加载到视图中的所有数据 - 但是,这需要比我认为应该花费更多的努力。
有没有办法简单地清除视图缓存?
答案 0 :(得分:65)
在app.js的状态定义中,您可以添加cache:false
来禁用缓存(请参阅Ionic文档中的Disable cache within state provider。或者,您可以保留缓存,除非您知道数据已更改。
$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 :(得分:19)
我偶然发现了一个类似的情况,其中登录其他用户向我展示陈旧/缓存的视图。您可以在州定义级别执行class Post < ActiveRecord::Base
belongs_to :bread
mount_uploader :attachment, AttachmentUploader
end
,但这会完全禁用应用中该状态的缓存。
当用户输入应用程序的登录/登录状态时,您可以清除所有缓存的视图和历史记录(如您所述)。似乎很理想。
cache: false
答案 2 :(得分:8)
您也可以在cache:false
:
$stateProvider
来执行此操作
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
答案 3 :(得分:4)
答案 4 :(得分:0)
这是一个老问题,我将解释究竟发生了什么以及如何解决它:
P.S:如果你想直接进入解决方案,只需立即向下滚动。
$ 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开发人员之前没有挖过代码,或者错过了这个简单的datail。有很多人为此感到痛苦。
为了说清楚,我想指出错误本身的位置(如果我们可以称之为bug),也许对开发者来说很方便:
self.clearCache = function(stateIds){
[...]
var viewElements = $element.children();
} 整个功能的作用基本上是:
使用JQLite获取所有元素 循环元素 检查一个元素是否等于StateIds数组中的元素并将其销毁;转到下一个元素。 检查循环中的元素是否被缓存或激活,并且在两种情况下都将其销毁 我不会深入研究这个,但调试它我可以看到元素来自var viewElements = $ element.children();不是所有视图内容的数组,甚至不是缓存的内容,有意或无意地不会遍历所有状态以清除所有匹配“ACTIVE”或“CACHED”的状态。如果您希望它遍历所有状态并销毁所有缓存的视图和数据,则需要明确传递stateIds数组参数。
除此之外还有另一个奇怪的行为,因为当我调试它时,我看到var viewElements数组填充了2个元素,而这2个元素来自同一个状态,一个解析为'CACHED'另一个解析器' ACTIVE',甚至解析if条件中使用的2种类型,根本没有清除缓存。
我个人认为这是某种错误的实施或被错误地广泛使用。事实是,有很多人对此表示不满,开发人员甚至没有给出这个简单的解释。