是否可以清除 Ionic 中的视图缓存?
Is it possible to clear the view cache in Ionic?
我目前正在做一个 Angular/Ionic/Cordova 项目,我们最近升级到了最新的 Ionic 测试版。从项目之前使用的版本来看,这引入了视图缓存。然而,这样做也引入了一个问题。
该应用程序面向客户并且非常以数据为中心。然而,目前用户必须进行身份验证才能查看与其帐户关联的数据;当用户注销并登录到另一个帐户时,因为视图仍被缓存,他们会看到最后一个帐户的视图。
当用户登录时,应用程序仍应缓存视图,因为这有助于使应用程序感觉更快,但应在用户注销时清除缓存。
设置 cache-view="false"
不是一个选项,因为它会完全禁用缓存。
我也试过设置 $ionicConfig.views.maxCache(0);
然后恢复到默认值 10,希望这样做能清除缓存,但没有效果。
我能想到的最后一件事是在用户登录时触发事件以刷新当前加载到视图中的所有数据 - 但是,这比我认为应该花费更多的努力。
有没有简单清除视图缓存的方法?
您是否正在寻找这样的东西?:
$ionicHistory.clearCache();
编辑:
Ionic 的 github 中存在问题:
Issue
在 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 才能 return 一个承诺。查看我在此拉取请求中所做的更改,并将您现在拥有的 clearCache 实现与我的进行比较:https://github.com/driftyco/ionic/pull/3724
我偶然发现了一个类似的场景,即与另一个用户一起登录时向我显示 stale/cached 视图。您可以在状态定义级别执行 cache: false
,但这会在您的应用程序中完全禁用该状态的缓存。
您可以做的是在用户进入应用程序的 signin/login 状态时清除所有缓存的视图和历史记录(如您所说)。看起来很理想。
// code inside your signin controller
$scope.$on("$ionicView.enter", function () {
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
});
您也可以在 $stateProvider
中设置 cache:false
:
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
好吧,这是一个老问题,我将解释真正发生的事情以及如何解决它:
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 开发人员之前没有深入研究过代码,或者错过了这个简单的数据。有很多人为此而苦恼。
只是为了crystal清楚,我想指出错误本身在哪里(如果我们可以称之为错误),也许对开发人员来说很方便:
self.clearCache = 函数(stateIds){
[...]
var viewElements = $element.children();
}
整个函数所做的基本上是:
使用 JQLite 获取所有元素
循环元素
检查 StateIds 数组中的元素是否等于一个并销毁它;转到下一个元素。
检查循环中的元素是否已缓存或处于活动状态,并且在两种情况下都将其销毁
我不会深入研究这个但是调试它我可以看到从 var viewElements = $element.children(); 获得的元素;不是您所有视图内容的数组,甚至不是缓存的内容,无论有意还是无意,它都不会遍历所有状态以清除所有匹配 'ACTIVE' 或 'CACHED' 的状态。如果您希望它遍历所有状态并销毁所有缓存的视图和数据,您需要显式传递 stateIds 数组参数。
除此之外还有另一个奇怪的行为,因为当我调试它时我看到 var viewElements 数组充满了 2 个元素,而这 2 个元素来自相同的状态,其中一个解析为 'CACHED' 'ACTIVE' 的另一个解析器,甚至解析为 if 条件中使用的 2 种类型,缓存根本没有被清除。
我个人认为这是某种错误的实现或错误地广泛使用。事实上,有很多人为此绞尽脑汁,而开发者甚至没有给出这个简单的解释。
我目前正在做一个 Angular/Ionic/Cordova 项目,我们最近升级到了最新的 Ionic 测试版。从项目之前使用的版本来看,这引入了视图缓存。然而,这样做也引入了一个问题。
该应用程序面向客户并且非常以数据为中心。然而,目前用户必须进行身份验证才能查看与其帐户关联的数据;当用户注销并登录到另一个帐户时,因为视图仍被缓存,他们会看到最后一个帐户的视图。
当用户登录时,应用程序仍应缓存视图,因为这有助于使应用程序感觉更快,但应在用户注销时清除缓存。
设置 cache-view="false"
不是一个选项,因为它会完全禁用缓存。
我也试过设置 $ionicConfig.views.maxCache(0);
然后恢复到默认值 10,希望这样做能清除缓存,但没有效果。
我能想到的最后一件事是在用户登录时触发事件以刷新当前加载到视图中的所有数据 - 但是,这比我认为应该花费更多的努力。
有没有简单清除视图缓存的方法?
您是否正在寻找这样的东西?:
$ionicHistory.clearCache();
编辑:
Ionic 的 github 中存在问题: Issue
在 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 才能 return 一个承诺。查看我在此拉取请求中所做的更改,并将您现在拥有的 clearCache 实现与我的进行比较:https://github.com/driftyco/ionic/pull/3724
我偶然发现了一个类似的场景,即与另一个用户一起登录时向我显示 stale/cached 视图。您可以在状态定义级别执行 cache: false
,但这会在您的应用程序中完全禁用该状态的缓存。
您可以做的是在用户进入应用程序的 signin/login 状态时清除所有缓存的视图和历史记录(如您所说)。看起来很理想。
// code inside your signin controller
$scope.$on("$ionicView.enter", function () {
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
});
您也可以在 $stateProvider
中设置 cache:false
:
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
好吧,这是一个老问题,我将解释真正发生的事情以及如何解决它:
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 开发人员之前没有深入研究过代码,或者错过了这个简单的数据。有很多人为此而苦恼。
只是为了crystal清楚,我想指出错误本身在哪里(如果我们可以称之为错误),也许对开发人员来说很方便:
self.clearCache = 函数(stateIds){
[...]
var viewElements = $element.children();
} 整个函数所做的基本上是:
使用 JQLite 获取所有元素 循环元素 检查 StateIds 数组中的元素是否等于一个并销毁它;转到下一个元素。 检查循环中的元素是否已缓存或处于活动状态,并且在两种情况下都将其销毁 我不会深入研究这个但是调试它我可以看到从 var viewElements = $element.children(); 获得的元素;不是您所有视图内容的数组,甚至不是缓存的内容,无论有意还是无意,它都不会遍历所有状态以清除所有匹配 'ACTIVE' 或 'CACHED' 的状态。如果您希望它遍历所有状态并销毁所有缓存的视图和数据,您需要显式传递 stateIds 数组参数。
除此之外还有另一个奇怪的行为,因为当我调试它时我看到 var viewElements 数组充满了 2 个元素,而这 2 个元素来自相同的状态,其中一个解析为 'CACHED' 'ACTIVE' 的另一个解析器,甚至解析为 if 条件中使用的 2 种类型,缓存根本没有被清除。
我个人认为这是某种错误的实现或错误地广泛使用。事实上,有很多人为此绞尽脑汁,而开发者甚至没有给出这个简单的解释。