我正在寻找一种获取iframe contentWindow对象的方法,并在用户执行某些操作后向其发布消息。我目前的解决方案根本没有角度感觉好(特别是从控制器访问DOM)。
我创建了一个说明问题的plunker: http://plnkr.co/edit/aXh4jydWGWfK3QQD4edd
执行postMessage是一种更有棱角的方式吗?
控制器:
app.controller('Main', function($scope) {
$scope.click = function() {
var iframe = document.getElementById("inner").contentWindow;
iframe.postMessage("Hello iframe", '*');
}
});
HTML:
<body ng-controller="Main">
<button ng-click="click()">send message</button>
<iframe id="inner" src="inner.html"/>
</body>
答案 0 :(得分:3)
我知道你的问题已经超过一年了,但我最近有类似的需求,所以我想我会发布我的解决方案。最初我有像你发布的东西,但正如你所指出的那样,这并不是非常“有角度”。它也不容易测试,我认为它也不是非常“Angular”。
相反,我重构了我的代码以实现iframe
作为指令。然后我从应用程序的控制器发出$broadcast()
个事件并让指令听取它们。这段代码可能会有相当多的改进,但感觉更像“Angular”并且避免直接触摸DOM。
'use strict';
angular.module('app')
.directive('angularIframe', ['$rootScope', function($rootScope) {
return {
restrict: 'E',
replace: true,
template: '<iframe id="game" src="/iframe/index.html" width="100%" height="100%" frameboarder="0" scrolling="no"></iframe>',
link: function(scope, elem) {
var off = $rootScope.$on('app.postmessage', function(ev, data, targetOrigin) {
var str = JSON.stringify(data);
targetOrigin = targetOrigin || '*';
elem[0].contentWindow.postMessage(str, targetOrigin);
});
// See: http://stackoverflow.com/a/14898795/608884
elem.on('$destroy', function() {
off();
});
}
};
}]);
然后,您可以通过在应用程序中的某处添加<game></game>
来使用此指令。
在控制器中,您现在可以广播app.postmessage
事件以及一些数据,以便在postMessage()
上调用iframe
:
var myData = { foo: 'bar' };
$rootScope.$broadcast('app.postmessage', myData);