【问题标题】:Read AngularJS expressions in a script outside the controller function在控制器函数之外的脚本中读取 AngularJS 表达式
【发布时间】:2016-12-27 09:10:14
【问题描述】:

因为this thread中的以下引用

最好的做法是永远不要使用 JQuery 或 angular.element() 在控制器内进行 DOM 操作。控制器仅用于我们的业务逻辑。

我已将一个调用 CodeMirrorJQuery 的大函数移到控制器外部。 big函数用于合并两个textarea的内容。 JSBin

HTML:

<div ng-app="myApp" ng-controller="myCtrl">
  <textarea ng-model="area1">area1</textarea>
  <textarea ng-model="area2">area2</textarea>
  <div>First: {{area1}}, {{area2}}</div>
  <div id="output"></div>
  <script>
    function bigfunction(area1, area2) {
      // a big function, the following is for the sake of simplicity
      return "Second: " + area1 + ", " + area2
    }
    var output = bigfunction({{area1}}, {{area2}});
    $("#output").html(output)
  </script>
</div>

Javascript:

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {
    $scope.area1 = "initial textarea1";
    $scope.area2 = "initial textarea2"
});

有谁知道为什么脚本中的{{area1}}{{area2}} 无法识别?

【问题讨论】:

  • 我认为你不能在javascript中使用bigfunction({{area1}}, {{area2}})
  • $("#output").html({{area1}}) 在脚本中也不起作用...
  • 是的。检查下面的答案。我认为这会对你有所帮助。

标签: angularjs angularjs-scope


【解决方案1】:

问题在于您将 JavaScript 与 AngularJS 模板混合在一起。

var output = bigfunction({{area1}}, {{area2}});

您不能期望内联 JavaScript 可以使用 AngularJS 模板工作。以下是发生的情况:加载 HTML 文件(模板)并解析并执行内联 JS。它失败是因为它包含错误的语法 ({{area1}})。这发生在 AngularJS 甚至加载之前。此外,JavaScript 代码只评估一次,因此即使模板实际上用字符串替换了{{area1}},代码也不会被重新评估,也不会产生不同的输出。您将需要完全改变您的方法。

我猜您想在控制器外部执行两个范围变量的连接,并可能为此添加额外的逻辑。您可以将代码移动到服务中,然后在控制器中使用它,或者使用指令(我不知道您的确切用例,所以我很难说哪种方法更有意义)。

由于您描述的是两个模型值的简单串联,因此指令似乎是有意义的。您的 HTML 可能如下所示:

<div ng-app="myApp" ng-controller="myCtrl">
    <textarea ng-model="area1">area1</textarea>
    <textarea ng-model="area2">area2</textarea>
    <div>First: {{area1}}, {{area2}}</div>
    <output area1="area1" area2="area2"></output>
</div>

在 JS 中,添加这个简单的指令:

app.directive('output', function() {
    return {
        restrict: 'E',
        template: '<div id="output">Second: {{area1}}, {{area2}}</div>',
        scope: {
            area1: "=",
            area2: "="
        }
    };
});

如果出于某种原因您希望在指令中添加额外的逻辑,您可以随时在链接函数中执行此操作。

如果您要添加一项服务,HTML 将再次只需要稍作改动:

<div ng-app="myApp" ng-controller="myCtrl">
    <textarea ng-model="area1">area1</textarea>
    <textarea ng-model="area2">area2</textarea>
    <div>First: {{area1}}, {{area2}}</div>
    <div>{{output}}</div>
</div>

JS 可能是这样的:

app.controller('myCtrl', function($scope, joiner) {
    $scope.area1 = "initial textarea1";
    $scope.area2 = "initial textarea2";
    $scope.$watchGroup(["area1", "area2"], function() {
        $scope.output = joiner.join($scope.area1, $scope.area2);
    });
});
app.service('joiner', function() {
    this.join = function(a1, a2) {
        return "Second: " + a1 + ", " + a2;
    };
});

该服务可以包含您需要的任何逻辑。

【讨论】:

  • 感谢您的出色回答。我把这两个 JSBin (directive, service) 放在这里记录一下。
【解决方案2】:

script 标签似乎无法访问角度变量。请参阅Pass Angular scope variable to Javascript 以检查解决方案。

【讨论】:

    【解决方案3】:

    你可以这样试试:

    $scope.area1 = "initial textarea1";
    $scope.area2 = "initial textarea2";
    function bigfunction(area1, area2) {
      // a big function, the following is for the sake of simplicity
      return "Second: {{area1}} {{area2}}" 
    }
    var output = bigfunction($scope.area1, $scope.area2);
    $compile(angular.element(document.querySelectorAll('#output')[0]).html(output))($scope);
    

    或者你可以试试这样的指令:

    app.directive('outputDir', function() {
        return {
            restrict: 'EA',
             scope: {
                area1: "=",
                area2: "="
            },
            template: '<div>Second: {{area1}}, {{area2}}</div>'    
        };
    });
    

    一切顺利。

    【讨论】:

    • 你的意思是把bigfunction放在app.controller('myCtrl', function($scope) { ... });里面吗?这不是我想做的……
    • 你只能在那里做。如果您真的不想在控制器中执行此操作,请将其移至指令中。
    【解决方案4】:

    你可以试试这个:

    <script>
        window.onload=function bigfunction() {
        var area1=angular.element(document.querySelector('[ng-controller="myCtrl"]')).scope().area1;
        var area2=angular.element(document.querySelector('[ng-controller="myCtrl"]')).scope().area2;
        result= "Second: " + area1 + ", " + area2;
        $("#output").html(output);
    }
    </script>
    

    你可以通过这种方式在javascript中检索angular js范围变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多