Angularjs:调用 iframe 中的其他范围

IT技术 javascript angularjs angularjs-scope
2021-02-14 07:05:39

在我的测试中,给定了 2 个文档,A 和 B。在 A 文档中,有一个 iframe,iframe 源是 B 文档。我的问题是如何修改B文件中某个范围的变量?

这是我的代码:一个文件

<html lang="en" ng-app="">
<head>
  <meta charset="utf-8">
  <title>Google Phone Gallery</title>
  <script type='text/javascript' src="js/jquery-1.10.2.js"></script>
  <script type='text/javascript' src="js/angular1.0.2.min.js"></script>
  <script>
  var g ;
function test($scope,$http,$compile)
{
    $scope.tryget = function(){

        var iframeContentWindow = $("#iframe")[0].contentWindow;
        var iframeDOM = $("#iframe")[0].contentWindow.document;
        var target = $(iframeDOM).find("#test2");
        var iframeAngular = iframeContentWindow.angular;
        var iframeScope = iframeAngular.element("#test2").scope();
        iframeScope.parentcall();
        iframeContentWindow.angular.element("#test2").scope().tempvalue = 66 ;
        iframeScope.tempvalue = 66;
        iframeContentWindow.tt = 22;
        iframeScope.parentcall();
        console.log(iframeScope.tempvalue);
        console.log(angular.element("#cont").scope());
    }
}

  </script>
</head>
<body>

<div ng-controller="test">
        <div id="cont" >
            <button ng-click="tryget()">try</button>
        </div>
</div>
<iframe src="test2.html" id="iframe"></iframe>

</body>
</html>

我的B文件:

<!doctype html>
<html lang="en" ng-app="">
<head>
  <meta charset="utf-8">
  <title>Google Phone Gallery</title>
  <script type='text/javascript' src="js/jquery-1.10.2.js"></script>
  <script type='text/javascript' src="js/angular1.0.2.min.js"></script>
  <script>
var tt =11;
function test2($scope,$http,$compile)
{
    console.log("test2 controller initialize");
    $scope.tempvalue=0;
    $scope.parentcall = function()
    {
        $scope.tempvalue = 99 ;
        console.log($scope.tempvalue);
        console.log(tt);
    }
}

  </script>
</head>
<body>

<div ng-controller="test2" id="test2">
        <div id="cont" >
            <button ng-click="parentcall()">get script</button>
        </div>
        {{tempvalue}}
</div>

</body>
</html>

注意:实际上有一些方法可以做到这一点,我觉得它像一个黑客而不是完成它的正确方法:那就是在 b 文档中创建一个按钮,然后用 angularjs ng-click 绑定。之后A文档jquery“触发”点击按钮。

4个回答

要在两个方向(父到 iFrame,iFrame 到父)访问和通信,如果它们都在同一个域中,并且可以访问 angular 范围,请尝试执行以下步骤:

*您不需要父级引用 angularJS 库...

从父级调用子 iFrame

1.从父元素获取子 iFrame 元素(答案链接):

document.getElementById("myIframe").contentWindow

2.访问元素的作用域:

document.getElementById("myIframe").contentWindow.angular.element("#someDiv").scope()

3.调用作用域的函数或属性:

document.getElementById("myIframe").contentWindow.angular.element("#someDiv").scope().someAngularFunction(data);

4.在运行函数的逻辑/更新属性后调用 $scope.$apply(链接到 Mishko 的答案):

$scope.$apply(function () { });

  • 另一种解决方案是在 iFrame 之间共享范围,但是您需要在双方都有角度:(链接到答案和示例

从子 iFrame 调用父级

  1. 调用父函数:

parent.someChildsFunction();

如有必要,还将更新如何跨域进行操作。

Necro,当然,但想在 .scope() 上给我 2cents。我曾使用过 AngularJS 的混蛋实现。它们主要是 JQuery 和 JSP,并带有 Angular 用于模板化。在每个 JSP 文件中,我们都有一个 getScope() 函数并且经常滥用 $apply()。它“有效”但显然并不理想。我想我的观点是 .scope() 在生产中可能不可用,但如果生产应用程序依赖于启用调试,请不要感到惊讶。
2021-04-20 07:05:39
感谢您的出色回答。Angular 1.2x 引入了 $evalAsync() 方法,该方法避免了将 $timeout 与 $apply 一起使用。在早期版本的 Angular 中推荐使用 $timeout 以保证更改会在 $digest 循环中被接受(否则可能会导致竞争条件)。
2021-04-21 07:05:39
警告!.scope() 不是生产方法。它仅用于调试,并在生产模式下被删除!docs.angularjs.org/guide/production
2021-04-24 07:05:39
乌里戈,这很棒而且很巩固。跨域怎么做?
2021-04-30 07:05:39
我想补充一点,您可以像这样从 iframe 中获取父作用域: var $scope = parent.angular.element('#element-id').scope();
2021-05-05 07:05:39

您应该能够从 iFrame 获取父作用域:

var parentScope = $window.parent.angular.element($window.frameElement).scope();

然后您可以调用父方法或更改父变量(但请记住调用parentScope.$apply以同步更改)

在 Angular 1.3.4 上测试

这真的救了我!!
2021-04-24 07:05:39
警告!.scope() 不是生产方法。它仅用于调试,并在生产模式下被删除!docs.angularjs.org/guide/production
2021-05-10 07:05:39
@JamiePate 你是对的。我认为我们要么不禁用调试信息,要么找到其他解决方案。
2021-05-11 07:05:39

我认为与 iframe 通信的最佳方式是使用 window.top。如果您希望 iframe 获得父级的作用域,您可以window.scopeToShare = $scope;在控制器中进行设置,并且 iframe 页面可以访问它window.top.scopeToShare

如果您希望您的父母获得 iframe 范围,您可以使用

window.receiveScope = function(scope) {
  scope.$on('event', function() {
    /* Treat the event */
  }
};

并在 iframe 控制器调用中 window.top.giveRootScope($rootScope);

警告:如果您多次使用此控制器,请确保使用附加 ID 来标识您想要的范围。

这个很简单,对我有用:

在 iframe 页面的控制器代码中:

$window.parent.window.updatedata($scope.data);

在父页面控制器代码中:

window.updatedata = function (data) {
 $scope.$apply(function () {
     $scope.data = data
   }
 }