AngularJS向iframe发送postmessage

5

我正在寻找一种方法来获取iframe的contentWindow对象,并在用户执行某些操作后向其发送消息。我的当前解决方案在使用angular时感觉不太好(特别是从控制器中访问DOM)。

我创建了一个展示该问题的plunker: http://plnkr.co/edit/aXh4jydWGWfK3QQD4edd

是否有更多适用于angular的方法来执行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>
1个回答

4
我知道这个问题已经过去一年了,但我最近有类似的需求,所以我想发表我的解决方案。起初,我像您发布的那样,但正如您指出的那样,这不太符合“Angular”的风格。它也不容易进行测试,这也不太符合“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: https://dev59.com/g2Up5IYBdhLWcg3w-Laz#14898795
                elem.on('$destroy', function() {
                    off();
                });

            }
        };
    }]);

您可以通过在应用程序中添加<game></game>来使用此指令。

在控制器中,您现在可以广播app.postmessage事件以及一些数据来调用iframe上的postMessage()

var myData = { foo: 'bar' };
$rootScope.$broadcast('app.postmessage', myData);

4
为什么要踩我?如果我的回答不好或者有待改进,留下评论指出问题会更有帮助。 - NoobsArePeople2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接