如何在指定时长后刷新iframe中打开的页面?
解决方案:iframe定时刷新(兼容同域/跨域,不修改Scope)
没问题,针对你的需求——在指定秒数后刷新iframe,且不想修改scope里的URL值,同时解决跨域场景下的SecurityError问题,我给你分场景提供可行方案:
一、同域页面刷新(自有页面)
如果iframe加载的是同域页面,你可以直接操作iframe的contentWindow来刷新,不需要修改任何scope变量,结合AngularJS的$timeout服务还能避免digest cycle问题:
// 在你的AngularJS控制器中注入$timeout angular.module('yourApp').controller('YourCtrl', ['$timeout', function($timeout) { const vm = this; // 定义刷新方法,x为秒数(大于5) vm.refreshIframe = function(x) { $timeout(() => { const iframe = document.getElementById('remotePageFrame'); if (iframe) { try { // 同域下直接强制刷新内部页面(不走缓存) iframe.contentWindow.location.reload(true); } catch (err) { // 自动捕获跨域错误,切换到跨域方案 vm.refreshCrossDomainIframe(iframe); } } }, x * 1000); // 转成毫秒单位 }; // 调用方法:比如10秒后刷新 vm.refreshIframe(10); }]);
二、跨域页面刷新(第三方页面)
当iframe加载外部域名页面时,浏览器的同源策略会阻止你访问contentWindow,这时我们可以通过重新设置iframe的src属性来实现刷新——完全不需要修改scope里的URL,直接操作DOM元素即可:
单个iframe的刷新代码
// 同样在控制器中注入$timeout angular.module('yourApp').controller('YourCtrl', ['$timeout', function($timeout) { const vm = this; vm.refreshCrossDomainIframe = function(iframe) { const currentSrc = iframe.src; // 从DOM元素获取当前实际URL,不依赖scope // 先设置为空白页,确保旧页面完全卸载 iframe.src = 'about:blank'; // 短暂延迟后恢复原URL,触发浏览器重新加载 $timeout(() => { iframe.src = currentSrc; }, 100); }; // 定时刷新方法 vm.scheduleRefresh = function(x) { $timeout(() => { const iframe = document.getElementById('remotePageFrame'); if (iframe) { vm.refreshCrossDomainIframe(iframe); } }, x * 1000); }; // 调用:比如15秒后刷新 vm.scheduleRefresh(15); }]);
循环生成的多个iframe刷新
如果你是循环生成多个iframe(加载多个外部页面),可以通过class选择器批量处理:
先修改iframe的HTML,统一加上标识class:
<iframe sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts" class="page-iframe" ng-show="$ctrl.getFrameURL(item) !== 'Default URL'" ng-src="{{$ctrl.getFrameURL(item)}}" width="100%" height="100%" scrolling="yes" frameBorder="0" ></iframe>
然后在控制器中批量刷新:
vm.refreshAllIframes = function(x) { $timeout(() => { const iframes = document.querySelectorAll('.page-iframe'); iframes.forEach(iframe => { vm.refreshCrossDomainIframe(iframe); }); }, x * 1000); }; // 调用:比如20秒后刷新所有iframe vm.refreshAllIframes(20);
关键说明
- 为什么不影响scope?
我们直接从DOM元素获取当前的src值,再重新设置,完全没有修改$ctrl.getFrameURL()返回的scope变量,所以scope的状态不会被改变。 - 跨域场景的原理:
浏览器允许修改iframe的src属性(即使是跨域URL),重新设置src会让浏览器重新发起请求加载该URL,完美避开了同源策略对contentWindow的访问限制。 - 关于sandbox属性:
你当前设置的sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts"是没问题的,allow-same-origin不会让外部页面和父页面同源,只是允许外部页面保持自身的源,不影响刷新逻辑。
内容的提问来源于stack exchange,提问作者Abdul Waheed
相关产品推荐
相关产品推荐

