Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何基于值相等和引用相等进行观看?_Javascript_Angularjs_Watch - Fatal编程技术网

Javascript 如何基于值相等和引用相等进行观看?

Javascript 如何基于值相等和引用相等进行观看?,javascript,angularjs,watch,Javascript,Angularjs,Watch,AngularJS中的函数接受可选的第三个参数 如果为false(默认值),则每当监视的参考发生变化时,手表将触发。如果为true,则每当监视对象根据更改时,监视将触发(这基本上意味着存储在监视对象中的值必须已更改) 现在,我正在寻找一种方法,如果被监视的引用或其内容发生了变化,让手表启动其功能。有没有办法做到这一点 举一个我所看到的困难的例子: 假设我有一组内容可编辑的对象: var allItems = [{id: 1, a: []}, {id: 2, a: [2, 3, 5]}, {id

AngularJS中的函数接受可选的第三个参数

如果为
false
(默认值),则每当监视的参考发生变化时,手表将触发。如果为
true
,则每当监视对象根据更改时,监视将触发(这基本上意味着存储在监视对象中的值必须已更改)

现在,我正在寻找一种方法,如果被监视的引用或其内容发生了变化,让手表启动其功能。有没有办法做到这一点


举一个我所看到的困难的例子:

假设我有一组内容可编辑的对象:

var allItems = [{id: 1, a: []}, {id: 2, a: [2, 3, 5]}, {id: 3, a: [4, 6]}, {id: 4, a: []}];
“我的编辑器”作用域上的字段接收对
A
属性值的引用。例如,如果选择了项目1,则会出现以下情况:

$scope.currentItem = [];
此外,我在该字段上注册了一块手表,用于检查值是否相等:

$scope.$watch('currentItem', watchFunc, true);
现在,我必须区分两种情况:

  • 用户使用编辑器UI将所选项目中的
    []
    扩展为
    [4,6]
  • 用户选择项目3
watchFunc
中,乍一看,这两个更改似乎是相同的。为了区分是否选择了新项目,我需要以某种方式保留以前的ID,如果它与当前ID不同,我需要忽略更改(因为数据中没有编辑任何内容,只切换了选定的项目)。然后,我需要使用
watchFunc
将当前项目ID设置为下一次调用的上一个ID

但是,在以下情况下,这是有问题的:

  • 选择项目1
  • 用户选择项目4
  • 用户在第4项中添加了一些内容
  • 这里的问题是,第二个动作不会根据
    角度.equals
    触发手表。因此,当选择更改时,所选项目ID将不会更新。相反,在步骤3中会注意到不同的项目ID,这会导致忽略实际的编辑操作


    显然,这个例子非常简单;实际上,我的对象图由对象的嵌套数组组成,每个数组都有不同的相关属性。

    工作JSFIDLE:

    希望这就是你想要的

    测试场景:

    1. Select 1
    2. Input 4 => Add
    3. Input 6 => Add
    4. Select 3
    5. $watch occurs
    
    AngularJS:

    var myApp = angular.module('myApp',[]);
    
    myApp.controller('myCtrl', myCtrl);
    
    function myCtrl($scope) {
        $scope.allItems = [{id: 1, a: []}, {id: 2, a: [2, 3, 5]}, {id: 3, a: [4, 6]}, {id: 4, a: []}];
        $scope.currentItemObject = {};
        $scope.currentItem = [];
    
        $scope.updateCurrentItem = function(item){
            $scope.currentItem = angular.copy(item.a);
        };
    
        $scope.addItem = function(){
          if($scope.newItem !== undefined){
            $scope.currentItem.push($scope.newItem);
            $scope.newItem = undefined;
          }
        };
    
        $scope.$watch(function(){ 
          return {id: $scope.currentItemObject.id, a: $scope.currentItem};
        },function(newValue, oldValue){
          if(newValue !== oldValue){
            console.log('$watch', $scope.currentItem);
            $scope.lastUpdate = new Date().toLocaleTimeString();
          }
        },true);
    }
    
    <div ng-controller="myCtrl">
      <label>Items: 
        <select ng-options="item as item.id for item in allItems" 
          ng-model="currentItemObject"
          ng-change="updateCurrentItem(currentItemObject)">
          <option style="display:none" value="">-- select item --</option>
        </select>
      </label>
      <div>
        <label>New item
          <input type="number" ng-model="newItem">
        </label>
        <button type="button" ng-click="addItem()">
          Add
        </button>
      </div>
    
      <div>
        Current item: {{currentItem}}  
      </div>
      <br/>
      <pre>
        Last update: {{lastUpdate}}
      </pre>
    </div>
    
    HTML:

    var myApp = angular.module('myApp',[]);
    
    myApp.controller('myCtrl', myCtrl);
    
    function myCtrl($scope) {
        $scope.allItems = [{id: 1, a: []}, {id: 2, a: [2, 3, 5]}, {id: 3, a: [4, 6]}, {id: 4, a: []}];
        $scope.currentItemObject = {};
        $scope.currentItem = [];
    
        $scope.updateCurrentItem = function(item){
            $scope.currentItem = angular.copy(item.a);
        };
    
        $scope.addItem = function(){
          if($scope.newItem !== undefined){
            $scope.currentItem.push($scope.newItem);
            $scope.newItem = undefined;
          }
        };
    
        $scope.$watch(function(){ 
          return {id: $scope.currentItemObject.id, a: $scope.currentItem};
        },function(newValue, oldValue){
          if(newValue !== oldValue){
            console.log('$watch', $scope.currentItem);
            $scope.lastUpdate = new Date().toLocaleTimeString();
          }
        },true);
    }
    
    <div ng-controller="myCtrl">
      <label>Items: 
        <select ng-options="item as item.id for item in allItems" 
          ng-model="currentItemObject"
          ng-change="updateCurrentItem(currentItemObject)">
          <option style="display:none" value="">-- select item --</option>
        </select>
      </label>
      <div>
        <label>New item
          <input type="number" ng-model="newItem">
        </label>
        <button type="button" ng-click="addItem()">
          Add
        </button>
      </div>
    
      <div>
        Current item: {{currentItem}}  
      </div>
      <br/>
      <pre>
        Last update: {{lastUpdate}}
      </pre>
    </div>
    
    
    项目:
    --选择项--
    新项目
    添加
    当前项:{{currentItem}}
    
    上次更新:{{lastUpdate}}
    注册2个带和不带第3个参数的侦听器?:)除了自定义方法之外,我想不出任何更简单的解决方案。从来没有必要这样做,但是。。这是一个非常有趣的问题。@StanislavKvitash:问题是,如果引用发生了更改,我需要抑制对值更改的反应。如果我只注册两名听众,我想我不能依赖他们的发言顺序。此外,引用更改之后可能会或可能不会有值更改,这取决于两个引用对象是否恰好具有相同的内容。@charlietfl:这可能是一个糟糕的设计。然而,总的来说,意识到某个元素以某种方式发生了变化,这听起来是合理的,对吗?不管某个值或整个引用是否已更改。。喜欢好。与angular 2一样?值在部分更改时应更改其引用,这样就无需执行深入比较。