【问题标题】:How to access scope angularjs from javascript?如何从 javascript 访问范围 angularjs?
【发布时间】:2023-03-19 15:57:01
【问题描述】:

我对这篇帖子 Pass Angular scope variable to Javascript 有同样的问题。但是我无法用他们的答案来实现我的解决方案。

我的 Angular 控制器

angular.module('App').controller('HomeController', [
    '$rootScope', '$scope', '$state', '$timeout', 'ReportService', 'MsgService',
    function($rootScope, $scope, $state, $timeout, ReportService, MsgService) {

        $scope.$on('$viewContentLoaded', function() {
            console.log('HomeController');
            $scope.get_locations();
        });

        // get locations
        $scope.get_locations = function() {
            var data = {};
            // call http get to my api
            MsgService.get_all_locations(data, function(response) {
                if (response.code == 1) { // success
                    $scope.locations_array = response.data; // data that I want to access to script
                } else {
                    alert(response.message);
                }
            });
        }
    }
]);

我的 HTML

<div id="map" ng-controller="HomeController">{{locations_array}}</div> // {{locations_array}} scope have the result that I want
<script type="text/javascript">

$(document).ready(function() {
    var data = $('[ng-controller="HomeController"]').scope().$parent.locations_array;
console.log(data); // underfined

    //var $element = $('#map');
   // var scope = angular.element($element).scope();
   // console.dir(scope.$parent.locations_array); // underfined
});

</script>

我尝试从浏览器开发工具访问然后它可以访问范围。但我的代码无法访问它。

如何解决?

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    这里的直接问题是时间问题 - 您正试图从范围内读取locations_array早在值被填充之前。

    事件的顺序是这样的:

    1. ready 文档触发器事件,在 Angular 考虑启动之前,您的内联 JS 代码运行,尝试从尚不存在的范围读取值。
    2. Angular 引导您的 Angular 应用程序以响应文档的 ready 事件(这可能在 #1 之前,具体取决于页面上脚本的顺序)。这将调用HomeController 构造函数,它只为$viewContentLoaded 事件设置一个监听器。
    3. $viewContentLoaded 事件被广播,并且您对位置发起异步请求。
    4. 当它在一段时间后返回位置时,会将它们填充到示波器上。

    不要依赖.scope()

    除了时间问题之外,您的解决方案还有另一个主要问题 - 它依赖于 AngularJS 包含的调试信息。显然,它是默认设置,但可以disable this debug information 在生产中显着提高性能。

    如果其他人出现,可能在您离开之后,并尝试禁用调试信息以提高性能或出于其他原因(这是生产中的推荐做法),它将停止 .scope() 工作

    因此,依靠.scope(),您正在使禁用调试信息这一最佳实践和性能提升器在现在或将来对您的应用程序来说是不可能的,因为它会破坏事情。对于那个开发者来说,它根本不会破坏任何东西。

    因此,依赖.scope() 进行除调试以外的任何事情都应该是最后的手段。

    那我该怎么做呢?

    就像我提到的,这是一个时间问题 - 您需要等到这些位置最终被加载,然后才能运行依赖它们的代码。

    幸运的是,我们在 JS 中有许多选项来处理异步值 - 回调、承诺、RxJS 可观察对象等。选择你最喜欢的。

    示例:使用全局承诺

    在您的控制器中,在全局范围内创建一个 Promise(很奇怪,但它需要在 Angular 之外的某个地方),并在加载时使用位置数据解决该 Promise。

    var resolveLocations;
    window.locationsPromise = new Promise(function (resolve) { 
        resolveLocations = resolve;
    });
    angular.module('App').controller('HomeController', [
        '$rootScope', '$scope', '$state', '$timeout', 'ReportService', 'MsgService',
        function($rootScope, $scope, $state, $timeout, ReportService, MsgService) {
    
            $scope.$on('$viewContentLoaded', function() {
                console.log('HomeController');
                $scope.get_locations();
            });
    
            // get locations
            $scope.get_locations = function() {
                var data = {};
                // call http get to my api
                MsgService.get_all_locations(data, function(response) {
                    if (response.code == 1) { // success
                        resolveLocations(response.data); // resolve the promise
                        $scope.locations_array = response.data; // data that I want to access to script
                    } else {
                        alert(response.message);
                    }
                });
            }
        }
    ]);
    

    然后,您的普通(非角度)javascript(需要在您的 Angular javascript 文件加载后运行)可以使用该承诺在可用时对数据执行某些操作:

    <script type="text/javascript">
    
    $(document).ready(function() {
        window.locationsPromise.then(function (locations_array) {
            console.dir(locations_array);
            // do something with the data
        });
    });
    
    </script>
    

    可能有更好的方法

    在不知道为什么您认为需要在 Angular 之外访问这些数据的情况下,很难确定,但可能还有其他更好的方法来处理 Angular 代码和依赖它的其他 Javascript 代码之间的相互作用。

    也许您创建一个指令来集成 jQuery 插件或其他服务或其他任何东西,但由于 AngularJS 代码只是普通的 JS,因此无需将它们视为彼此分离的。您只需要把握好时机,就可以获得可用的数据。祝你好运!

    【讨论】:

    • 很好的解释!!。但这种方式会“脏”。我可以使用 localstorage 代替吗?在我可以从 js 获取数据之后。创建指令也是更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 2012-11-05
    • 2018-08-30
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    相关资源
    最近更新 更多