"Scope doesn't get associated with new element added in compile phase" 的意思是:作用域不会关联在编译阶段添加的新元素上。

35 浏览
0 Comments

"Scope doesn't get associated with new element added in compile phase" 的意思是:作用域不会关联在编译阶段添加的新元素上。

在下面的代码中,我试图在编译阶段添加一个按钮,并将ng-click分配给作用域中的一个方法。

在连接阶段,通过调试我发现“compiledEle”包含按钮,但ng-click不调用作用域方法。

angular.module("app", [])
        .controller("ctrl1", function($scope){
            $scope.myModelObj = {
                name: 'Ratnesh',
                value: 100
            };
        })
        .directive("dirOne",function($compile){
            return {
                restrict: 'E',
                scope: {
                    myModel : "="
                },
                compile: function(ele){
                    ele.append("")
                    return {
                        post: function($scope, compiledEle){
                            $scope.showAlert = function(){
                                alert("The button is clicked");
                            };
                        }
                    };
                }
            };
        });

为什么作用域方法不会绑定到编译阶段添加的按钮,但是如果在模板/模板URL中添加按钮,则可以绑定相同的内容。如果在连接阶段包含以下行,则该方法也将绑定:

$compile(compiledEle.contents())($scope);)

如果不是在连接阶段添加“$scope.showAlert”,而是在控制器中已经有该方法,则它将绑定到该方法!

    .controller("ctrl1", function($scope){
                $scope.myModelObj = {
                    name: 'Ratnesh',
                    value: 100
                };
                $scope.showAlert = function(){
                    alert("The button is clicked");
                };
            })

编译方法用于执行DOM操作,连接阶段用于将已编译的HTML链接到作用域。因此,我们可以在编译期间向DOM添加新元素,并在连接阶段添加新的作用域方法,那么我的期望在哪里出了差错?

admin 更改状态以发布 2023年5月21日
0
0 Comments

问题在于,在编译时,您的编译函数没有访问元素实例作用域的权限。您希望ng-click执行实例作用域的方法,但此时模板还未编译。\n\n我已经添加了注释来说明发生了什么:\n\n

app.directive("fromCompile", function($compile) {
  return {
    restrict: 'E',
    scope: {},
    compile: function(tElement) {
      // When AngularJS compiles the template element, it does not have
      // access yet to the scope of the iElement, because the iElement does
      // not exist yet.
      // You want ng-click to execute a method of the iElement scope
      // which does not exist here yet because you are modifying the
      // template element, not the instance element.
      // This will not give you the effect you are looking for because it
      // will execute the function in a scope higher up the scope hierarchy.
      tElement.append('');
      return {
        post: function(scope, iElem, iAttrs) {
          scope.showAlert = function() {
            alert("This button was added using compile");
          };
        }
      };
    }
  };
});

\n\n为解决此问题,您可以使用模板,让AngularJS自动为您编译模板:\n\n

app.directive("fromTemplate", function($compile) {
  return {
    restrict: 'E',
    scope: {},
    template: "",
    link: function(scope, iElem, iAttrs) {
      scope.showAlert = function() {
        alert("This button was added using template");
      };
    }
  };
});

\n\n或者在元素实例的链接函数中手动编译模板(因为您可以在那里访问正确的作用域):\n\n

app.directive("fromLink", function($compile) {
  return {
    restrict: 'E',
    scope: {},
    link: function(scope, iElem, iAttrs) {
      var linkFn = $compile("");
      var button = linkFn(scope);
      iElem.append(button);
      scope.showAlert = function() {
        alert("The button was added using $compile in link function");
      };
    }
  };
});

\n\n我创建了一个带有所有代码和工作版本的Plunk,在这里。\n\n希望这可以帮到您!

0