В моем угловом приложении у меня есть несколько экземпляров $modal
, которые создаются следующим образом:
var modalInstance = $modal.open({
templateUrl: APP_CONFIG.TPL_PATH + '/path/template.html',
controller: 'TemplateController'//...
});
Проблема в том, что после просмотра этих модалов они кешируются, и если я их изменяю, я вынужден очистить кеш браузера. Не проблема на компьютере разработчика, но проблема, когда я предоставлю это приложение потенциальным пользователям.
Я нашел это как "решения" до сих пор:
// first one
$rootScope.$on('$stateChangeStart', function(event, next, current) {
$templateCache.remove(current.templateUrl);
}); // doesn't work because $modal doesn't change state
// second one
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
}); // mess Bootstrap UI which adds default partials directly to the $templateCache
// third one
$modal.open({
templateUrl: '/app/components/your-modal.html?bust=' + Math.random().toString(36).slice(2),
controller: 'YourModalController'
}); // ugly and inefficient - I have to change multiple code blocks for every modal
Есть ли достаточные решения? Заранее спасибо.
ИЗМЕНИТЬ
Дополнительный совет, который я получил, - это изменить данные шаблона и поместить их в файлы .js (т.е. <p>Data</p>
в <p>{{data}}</p>
и $scope.data = 'Data'
в .js). Здесь я вижу две проблемы. Как я могу быть уверен, что файл .js не кэшируется браузером? Как я могу добавить дополнительные изменения в структуру шаблона (дополнительные переменные), если он кешируется (т.е. в <p>{{data}}</p><img src='{{imageUrl}}>'
)?
4 ответа
Что ж, когда мы говорим о «достаточном», это вопрос вкуса и особой проблемы, но я нашел этот ответ вполне удовлетворительным:
Вы не можете удалить кеш браузера напрямую с помощью JavaScript. Это связано с требованием безопасности. И это немного неправильно - многие умные разработчики лучше знают, что хранить и что удалять. Но есть простой прием: использование ?keyword=hash
. Даже если страницы, которые вы видите, будут похожими, если для них будут разные хэши, браузер сохранит две версии страниц. Добавление ?keyword=hash
в каждый $model.open()
раздражает и непрофессионально (СУХОЙ, ПОЦЕЛУЙ). Давайте использовать угловой interceptors
тогда.
yourApp.factory('HttpInterceptor', function($templateCache, APP_CONFIG) {
return {
'request': function(request) {
if (request.method === 'GET' && $templateCache.get(request.url) === undefined) {
request.url += '?ver=' + APP_CONFIG.VERSION;
}
return request;
}
};
});
Поместите это в $httpProvider.interceptors
:
$httpProvider.interceptors.push('HttpInterceptor');
Теперь вы можете указать номер версии (например, взять его из репозитория или включить метки времени). Версия изменена - браузер загружает новую версию ваших шаблонов. Условие if $templateCache.get(request.url) === undefined
используется для фильтрации запросов на предварительно кэшированный (возможно, автоматически вставленный) контент. Идея перехватчиков взята отсюда: https://stackoverflow.com/a/25060769/4753661.
Добавьте следующий раздел в вашу веб-конфигурацию. Вам нужно будет очистить текущий кеш браузера вручную, но в дальнейшем перезагрузка страницы будет работать,
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache, no-store, must-revalidate" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="0" />
</customHeaders>
</httpProtocol>
</system.webServer>
Краткое описание предоставленных вариантов
Первый и второй варианты.
// first one
$rootScope.$on('$stateChangeStart', function(event, next, current) {
$templateCache.remove(current.templateUrl);
}); // doesn't work because $modal doesn't change state
// second one
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
}); // mess Bootstrap UI which adds default partials directly to the $templateCache
Вы, безусловно, не хотите произвольно очищать элементы от $templateCache
, что похоже на то, что делали ваши первые два варианта. Тогда Angular придется снова и снова добавлять представления в templateCache.
Третий вариант:
$modal.open({
templateUrl: '/app/components/your-modal.html?bust=' + Math.random().toString(36).slice(2),
controller: 'YourModalController'
}); // ugly and inefficient - I have to change multiple code blocks for every modal
Это фактически приведет к утечке памяти, потому что теперь у вас будет бесконечное количество шаблонов, добавляемых в $ templateCache.
Лучшие решения
Мой рекомендуемый ответ
Я бы рекомендовал переименовать ваш файл template.html
, чтобы иметь уникальные идентифицируемые имена.
< EM> т.е . modalTemplate_alertModal.html, modalTemplate_newEmployeeModal.html ...
Тогда вы действительно сможете использовать преимущества $templateCache
и повысить производительность.
Если вы абсолютно не можете переименовать файлы template.html
.
В этом случае вы можете удалить конкретный шаблон из templateCache, прежде чем открывать модальный.
//Get TemplateURL
var TemplateURL = APP_CONFIG.TPL_PATH + '/path/template.html';
//Remove Cached ModalTemplate
$templateCache.remove(TemplateURL);
//Open Modal
var modalInstance = $modal.open({
templateUrl: TemplateURL,
controller: 'TemplateController'//...
});
У меня может быть статический заголовок (т.е.
<h2>Create new entry</h2>
). А затем изменить его (_<h2>Create new user entry</h2>
). Если бы я ранее просматривал модал, я бы не получил обновленный заголовок без очистки кеша.
Основываясь на этом утверждении, вы действительно хотите использовать controller
и $scope
для обновления этих значений.
<h2>{{modalHeader}}</h2>
Затем, где бы вы ни определяли, какой заголовок должен быть обновлен, его значение
$scope.modalHeader = "Create new user entry";
Помните, что angularjs компилирует и управляет DOM
, единственный способ правильно изменить значения DOM
- использовать directives
.
Похожие вопросы
Связанные вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.