Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.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 如何在ng repeat only内使单击事件重新呈现受影响的项目(即,不运行$apply)?_Javascript_Html_Angularjs - Fatal编程技术网

Javascript 如何在ng repeat only内使单击事件重新呈现受影响的项目(即,不运行$apply)?

Javascript 如何在ng repeat only内使单击事件重新呈现受影响的项目(即,不运行$apply)?,javascript,html,angularjs,Javascript,Html,Angularjs,我的示例代码(下面)提出了两个问题: “renderthis”函数在加载页面时,每项调用两次 主要问题-单击按钮时,我假设在计算doit()表达式之后,ng click调用作用域上的$apply,这会导致每个项的两个DOM元素被重新呈现。。现在,我了解到这里每个项目的范围都以某种方式绑定到父范围,或者通过某种奇怪的隔离、转换或诸如此类的东西与之相关,这些我还没有掌握。。是否有一种方法可以使ng click only调用$digest在每个项或类似项的子范围内 这是我的密码: html: 或参见本

我的示例代码(下面)提出了两个问题:

  • “renderthis”函数在加载页面时,每项调用两次

  • 主要问题-单击按钮时,我假设在计算doit()表达式之后,ng click调用作用域上的$apply,这会导致每个项的两个DOM元素被重新呈现。。现在,我了解到这里每个项目的范围都以某种方式绑定到父范围,或者通过某种奇怪的隔离、转换或诸如此类的东西与之相关,这些我还没有掌握。。是否有一种方法可以使ng click only调用$digest在每个项或类似项的子范围内

  • 这是我的密码:

    html:

    或参见本plnkr:

    是否有一种方法可以使ng click only调用$digest在每个项或类似项的子范围内

    不。要实现此功能,您必须创建自己的指令

    ng click触发一个(参见“运行时”部分),它将(除其他外)检查所有$watches。视图中的每一组{}设置一个$watch。这就是为什么单击时会看到renderthis函数中的log()s

    我认为除非$watchs检测到变化,否则不会重新渲染任何内容

    关于“页面加载时每个项目调用两次”:

    (由于当检测到更改时,watchExpression可以在每个$digest循环中执行多次,因此请准备好对侦听器进行多次调用。)--


    @阿泰姆有一个好主意。总而言之,由于Angular在第一个$digest周期中发现了一些变化,因此它运行另一个周期以确保所有模型都稳定下来(没有变化)。

    在与@Mark进行了一些乒乓球之后(见下文),有人建议我将问题重新表述为这样的问题:“如何在ng repeat作用域内使单击事件仅重新呈现受影响的项目(即,不运行$apply)”这是为了强调,正如Mark所解释的,使用“ng click”本身是不太可能的,因为它发出硬编码的“$apply”,并运行摘要循环等(请参阅下文)

    我将接受我自己的答案,其中包括我自己版本的ng click,它使用$digest而不是$apply,因此不会触发所有ng-repeat'ed项目的重新呈现

    以下是修订后的ng click代码(xng click):

    下面是一个plnkr演示:


    .

    您可以尝试使用ngp本地单击而不是ng单击->

    请查看此plnkr:。单击其中一个按钮不会更改范围中的任何内容,但仍会为两个项目的范围调用“renderthis”函数。这是否意味着刚刚发生了重新渲染?如果“renderthis”呢“是一个功能,应该每个项目运行,并进行一些繁重的工作,我的列表中有10000个项目。”。。如果我自己绑定单击并调用scope.$digest,这不会发生,但我正在寻找一个更具角度性的解决方案。(@ayal,我在发布之前已经测试了您的plnkr。)因为在您的视图中有{}个
    renderthis()
    ,Angular会自动为此设置一个$watch。只要调用$apply,就会检查该手表,从而调用renderthis()方法。如果这对您意味着“渲染”,则正在进行渲染。(对我来说,“渲染”意味着浏览器必须重新绘制可见页面的一部分,因为DOM中的某些内容发生了更改——当您单击按钮时,DOM中的任何内容都不会更改。因此,对我来说,没有渲染)。作用域。$digest仍将导致检查视图中的所有$watches。无论此处的“render”是否正确,事实仍然是,如果该列表中有1000000个项目,单击其中一个项目的作用域将触发1000000个函数调用。。另外,请看这个forked plnkr(),在其中我不再使用ng click-我自己绑定click事件并调用$digest,这一次即使对范围进行了实际更改。在这种情况下,列表中的其他元素没有“呈现”(尽管对第一项的“renderthis”的双重调用对我来说仍然非常奇怪),这或多或少(可能更少)是我期望ng click会做的事情:。(代码几乎相同,只是它调用$digest)@ayal,我喜欢你的最后一把小提琴。虽然我认为我回答了提出的问题(即,否,ng click不能在事件发生的子作用域上仅运行$digest),但我建议1)将问题改写为以下内容:如何使ng repeat作用域内的click事件仅重新呈现受影响的项(即,不运行$apply)?2) 把你的最后一把小提琴作为答案,并接受它。我心里至少还有两个问题,所以我想参考这样的答案。这还没有经过彻底的测试,所以使用风险自负。如果你对此有所改进,请告诉我。
    <body ng-controller="MainCtrl">
         <ul>
            <li ng-repeat="item in items">
            <div>
             <span>{{item.title}}</span> 
             <span>{{renderthis()}}</span>
             <span>{{item.number}}</span>
             <button ng-click="doit()">CLIQUE!</button>
            </div>
            </li>
          </ul>
      </body>
    
    var app = angular.module('angularjs-starter', []);
    
    app.controller('MainCtrl', function($scope) {
      $scope.doit = function(){
        console.log('doing it for item with title --> ', this.item.title);
      }
      $scope.renderthis = function(){
        console.log('rendering this for item with title -->', this.item.title);
        return '|';
      }
      $scope.items = [{title: 'hello', number: 1}, {title: 'shalom', number: 42}];
    });
    
    var xngEventDirectives = {};
    
    angular.forEach(
      'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup'.split(' '),
      function(name) {
        var directiveName = directiveNormalize('xng-' + name);
        xngEventDirectives[directiveName] = ['$parse', function($parse) {
          return function(scope, element, attr) {
    
            var fn = $parse(attr[directiveName]);
            element.bind(name.toLowerCase(), function(event) {
            fn(scope, {$event:event});
            scope.$digest();
            });
          };
        }];
      }
    );