【问题标题】:angular directive one way binding changing value in controller角度指令单向绑定控制器中的更改值
【发布时间】:2016-03-23 22:59:02
【问题描述】:

我正在使用从控制器到指令的角度单向绑定。当我更新指令中的值时,它不应该更新控制器中的值。但它作为双向绑定工作。谁能找到我的错误。

angular.module("myApp",[])  
  .directive("myDirective",['$timeout', function ($timeout) {
    return {
      scope: {myValue: "&myAttribute"},
      template: '<input type="text" ng-model="myValue().name">',
      link: function (scope, iElm, iAttrs) {
        var x = scope.myValue();
        console.log(x);
        $timeout(function(){
          x.name= "directive";
        },4000);
      }
    };
  }]).controller("myController", function ($scope, $timeout) {
    $scope.someObject = {name: "test"};
    $timeout(function(){
      $scope.someObject.name= "controller";
    },2000);

});

http://plnkr.co/edit/9wihx1VYgKoTK00awN67?p=preview

【问题讨论】:

  • 我认为 & 将创建一个函数,该函数返回父作用域中 someObject 的值,docs.angularjs.org/api/ng/service/$compile,所以这不是单向的。
  • 是的,& 返回一个 getter 函数。所以应该是单向的
  • 它获得了一个对象的引用,所以指令和父作用域都有相同的引用,对对象属性的任何更改都会自然地出现在这两个地方
  • 有点离题,但如果您使用的是 Angular 1.5.x,您将可以使用 &lt; 绑定,这是单向的。

标签: javascript angularjs


【解决方案1】:

我不确定是否有更简单的方法,但您可以在隔离范围内使用带有@ 绑定的单向绑定,并在属性上添加观察者以更新指令中的对象更改。

@ 绑定从父级获取数据并将它们作为字符串传递给指令。要创建对象,您必须使用 scope.$eval(interpolatedStrValue)

(与其他答案中提到的“&”绑定不起作用,因为 getter 正在将引用传递给父对象。所以任何更改也会更新父对象。)

请看下面的演示或fiddle

angular.module('demoApp', [])
	.directive('oneWay', OneWay)
  .controller('mainController', MainController);
  

function OneWay($timeout, $parse) {
	return {
  	scope: {
    	myValue: '@myAttribute'
    },
  	template: '<input type="text" ng-model="myValue.name"/>',
    link: function(scope, element, attrs) {
    	console.log('link', scope.myValue);
      attrs.$observe('myAttribute', function(myValStr) {
      	scope.myValue = scope.$eval(myValStr);
        console.log('controller myValue obj', scope.myValue);
      });
      
      $timeout(function() {
      	console.log('change dir');
        scope.myValue.name = "directive changed";
       }, 4000);
      
      
    }
  }
}

function MainController($scope, $timeout) {
	$scope.testObj = {
  	name: 'before mod.'
  };
  
  $timeout(function() {
  	$scope.testObj.name = 'Controller modify';
  }, 2000);
  
  $timeout(function() {
  	$scope.testObj.name = '2nd Controller modify';
  }, 8000);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.9/angular.js"></script>
<div ng-app="demoApp" ng-controller="mainController">
  Controller: {{testObj.name}}<br/>
  Directive: <one-way my-attribute="{{testObj}}"/>
</div>

【讨论】:

    【解决方案2】:

    您应该使用“@”而不是“&”,如下所示

    scope: {myValue: "@myAttribute"}
    

    下面的链接解释

    What is the difference between & vs @ and = in angularJS

    【讨论】:

    • 使用@符号意味着你只会得到一个字符串值,所以模板必须看起来像 跨度>
    【解决方案3】:

    根据文档(对于 1.xx)https://docs.angularjs.org/api/ng/service/$compile & 将返回在父范围(一个 getter)中执行的属性表达式的值,在这种情况下是一个对象引用,并且更改任何对象的属性都将反映在两者中。

    不过,在指令作用域中对 myValue 的更改不会影响父作用域。

    【讨论】:

      猜你喜欢
      • 2023-03-25
      • 2016-06-08
      • 1970-01-01
      • 1970-01-01
      • 2016-08-06
      • 1970-01-01
      • 2015-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多