現在、Angular/Ionic/Cordovaプロジェクトに取り組んでいますが、最近、最新のIonicベータ版にアップグレードしました。プロジェクトが以前に使用していたバージョンから、これによりビューキャッシュが導入されました。ただし、そうすることで問題が発生しました。
アプリケーションは顧客向けであり、データ中心です。ただし、現在、ユーザーはアカウントに関連付けられたデータを表示するために認証する必要があります。ビューがまだキャッシュされているため、ユーザーがログアウトして別のアカウントにログインすると、最後のアカウントのビューが表示されます。
ユーザーがログインしているときにアプリがビューをキャッシュする必要があります。これにより、アプリがより速く感じられるようになりますが、ユーザーがログアウトするときにキャッシュを消去する必要があります。
cache-view="false"
を設定することは、キャッシュを完全に無効にするため、オプションではありません。
また、$ionicConfig.views.maxCache(0);
を設定して、デフォルトの10に戻すことを試みましたが、そうすることでキャッシュがパージされることを期待していますが、効果はありませんでした。
最後に考えられることは、ユーザーがログインするとイベントが発生し、ビューに現在ロードされているすべてのデータが更新されることです。ただし、これは思ったよりも少し手間がかかります。
ビューキャッシュを単純にクリアする方法はありますか?
App.jsの状態定義で、cache:false
を追加してキャッシュを無効にすることができます(Ionicドキュメントの 状態プロバイダー内のキャッシュを無効にする を参照してください。データが変更されたことがわかっている場合を除きます。
$state.go($state.currentState, {}, {reload:true})
$ionicHistory.clearCache().then(function(){ $state.go('app.fooState') })
後者では、Promiseを返すためにclearCacheが必要です。このプルリクエストで行った変更を確認し、現在持っているclearCacheの実装を私のものと比較してください。 https://github.com/driftyco/ionic/pull/3724
別のユーザーでログインすると、古い/キャッシュされたビューが表示されるという類似のシナリオに出くわしました。状態定義レベルでcache: false
を実行できますが、それはアプリのその状態のキャッシュを完全に無効にします。
むしろできることは、ユーザーがアプリケーションのサインイン/ログイン状態になったときに、キャッシュされたビューと履歴をすべてクリアすることです(あなたが言ったように)。理想的だ。
// code inside your signin controller
$scope.$on("$ionicView.enter", function () {
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
});
cache:false
で$stateProvider
を設定することでもできます:
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
さて、これは古い問題です。実際に何が起こるのか、どのように解決するのかを説明します。
追伸:ソリューションに直行したい場合は、すぐに下にスクロールしてください。
$ ionicHistory.clearCache()のコード:
`clearCache: function(stateIds) { return $timeout(function() {
$ionicNavViewDelegate._instances.forEach(function(instance) {
instance.clearCache(stateIds);
});
}`
したがって、ご覧のとおり、stateIdの配列であるstateIdsとして宣言された1つのパラメーターが必要です。実際、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 = function(stateIds){
[...]
var viewElements = $element.children();
}関数全体の基本は次のとおりです。
JQLiteを使用してすべての要素を取得する要素をループするStateIds配列内の要素が要素に等しいかどうかを確認し、それを破棄します。次の要素に移動します。ループ内の要素がキャッシュされているかアクティブであるかを確認し、どちらの場合でもそれを破壊しますが、これを深く掘り下げることはしませんが、それをデバッグすると、要素がvar viewElements = $ element.children();すべてのビューコンテンツの配列ではなく、キャッシュされたものであっても、意図的にまたはすべての状態をループして「ACTIVE」または「CACHED」に一致するすべての状態をクリアするわけではありません。すべての状態をループし、キャッシュされたすべてのビューとデータを破棄する場合は、stateIds配列パラメーターを明示的に渡す必要があります。
それに加えて、別の奇妙な動作があります。デバッグ中にvar viewElements配列が2つの要素でいっぱいになり、これらの2つの要素が同じ状態からのものであり、1つが「CACHED」に解決され、別のリゾルバが「ACTIVE」に解決されたため、キャッシュがまったくクリアされなかったif条件で使用される2つのタイプに解決することもできます。
個人的には、これは何らかの形で間違って実装されているか、誤って広く使用されていると思います。実際のところ、多くの人がこれに頭を悩ませており、開発者はこの簡単な説明さえしていません。