TOGOUTECH

javascript - 为什么我在 Angular JS 中得到两个方法调用?

coder 2024-05-16 原文

我有以下示例:

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
  $scope.testMethod = function() {
    alert('hi');
  }
});
<!DOCTYPE html>
<html>

<head>
  <script data-require="[email protected]" data-semver="1.5.0" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
</head>

<body ng-app="myApp">
  <div ng-controller="myCtrl">
    {{testMethod()}}
  </div>
</body>

</html>

我只在 View 模板中调用过一次该方法。但是为什么执行了两次呢?

最佳答案

当你在绑定(bind)表达式中使用函数时,Angular 将在每个 $digest 阶段重新计算表达式。这背后的原因是函数可以返回响应,但 Angular 无法知道结果是否不会在下一个函数调用中改变。

在这种情况下,Angular 确保它将以唯一可能的方式显示最新的正确的最新值 - 每次范围发生变化时调用该函数。

您会看到人们称此为“$digest phase”。它可能由于多种原因而发生。为了便于解释,我正在简化内容。如果您想了解更多信息,请阅读 https://docs.angularjs.org/guide/scope

作为一般规则 - 避免绑定(bind)到函数。相反,记住 $scope 变量中的函数响应并绑定(bind)到它。当项目中的绑定(bind)计数增加时,多次绑定(bind)到一个函数可能会导致性能问题。

编辑 - 对 sahbeewah 评论的回答(见下文)

让我们更改帖子示例。打开控制台并运行以下代码。

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
  var i = 0;

  $scope.testMethod = function() {
    alert('hi');

    i++;
    return i; // Return a different value every time
  }
});
<!DOCTYPE html>
<html>

<head>
  <script data-require="[email protected]" data-semver="1.5.0" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
</head>

<body ng-app="myApp">
  <div ng-controller="myCtrl">
    {{testMethod()}}
  </div>
</body>

</html>

出于示例目的,$scope.testMethod 在每次调用时返回不同的值很重要。

您会注意到以下几点:

  • “你好”提示会多次显示
  • 多次看到后会出现以下错误:

    Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

所以,发生了什么事?每次我们在这里更改 $scope 状态时,angular 都会运行另一个摘要阶段,直到它“稳定”(没有更多更改)。连续 10 个 $digest 阶段有限制。

在线程帖子中,当连接 Controller 时,angular 调用 $digest,然后,因为我们更改了 $scope,它又调用了一个摘要。如果我们从代码中删除所有绑定(bind),则只会出现一个摘要。

我们可以很容易地检查这一点。从示例中删除 {{testMethod()}} 行,然后在 Angular 代码中放置一个断点:$digest,第 16700 行(angular 1.5.0) .
在这一行你会看到 if ((dirty || asyncQueue.length) && !(ttl--)) {

您的断点现在只会命中一次。让我们看看上面的 2 行。 Angular 团队在那里写了一条有趣的评论:

// `break traverseScopesLoop;` takes us to here

这是一个不言自明的注释,如果我们转到第 16629 行,我们会看到

do { // "while dirty" loop

代码中有一个名为“dirty”的变量,它创建了一个do...while 循环。虽然范围是(检测到更改),但您将留在这个循环中。更改是指通过任何类型的绑定(bind) ($watch) 以任何方式使用的任何范围变量的任何更改。

这就是为什么我们在这里有 2 个 $digest 阶段。

您可以找到 Angular 1.5 here .出于调试目的,我已切换到非缩小版本。

关于javascript - 为什么我在 Angular JS 中得到两个方法调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36743457/

有关javascript - 为什么我在 Angular JS 中得到两个方法调用?的更多相关文章

  1. c# - 为什么我得到 "CS0472: The result of the expression is always true since a value of type int is never equal to null of type int?" - 2

    string[]arrTopics={"Health","Science","Politics"};我有一个if语句:if(arrTopics.Count()!=null)当我将鼠标悬停在上面的语句上时,它说:WarningCS0472:Theresultoftheexpressionisalwaystruesinceavalueoftypeintisneverequaltonulloftypeint?我不明白为什么会这样说。谁能帮帮我? 最佳答案 int永远不能等于null。int?

  2. c# - 为什么在将字符串转换为 float 时会出现 FormatException? - 2

    当我尝试将字符串转换为float时:Console.WriteLine(float.Parse("6.59"));它抛出一个异常:UnhandledException:System.FormatException:Inputstringwasnotinacorrectformat.atSystem.Number.ParseSingle(Stringvalue,NumberStylesoptions,NumberFormatInfonumfmt)当我这样尝试时:Console.WriteLine(Convert.ToSingle("6.59"));它抛出相

  3. 百万赞同:网络安全为什么缺人? 缺什么样的人? - 2

    1.网络安全为什么缺人?缺人的原因是有了新的需求以前的时候,所有企业是以产品为核心的,管你有啥漏洞,管你用户信息泄露不泄露,我只要做出来的产品火爆就行。这一切随着《网络安全法》、《数据安全法》、《网络安全审查办法》等一系列有关网络安全的法律法规出台戛然而止,上到国家下到个人都开始重视网络安全,你看最近的国家对滴滴进行网络安全审查就引发的大家的强烈关注就能感受到。按照新的网络安全法律法规要求,你的企业出了网络安全问题,不仅要处罚企业,还要连带处罚企业负责人,

  4. c# - 为什么在实现接口(interface)方法时允许虚拟? - 2

    我对接口(interface)有一个特定的查询。默认情况下,接口(interface)方法是抽象的和虚拟的,所以如果我们实现该接口(interface)并在类中给出定义,我们实际上会重写该方法,但是当我们在实现类中再次将方法标记为虚拟时,为什么编译器不考虑我们实际上是想隐藏原来的接口(interface)虚方法。如果我们在基类中有一个虚方法并且派生类再次将该方法标记为虚方法,在这种情况下编译器会警告您隐藏了基类方法,因此如果您有意隐藏基类方法,请使用new.publicinterfaceITestInterface{voidvirtualmethod();//thismethodisb

  5. c# - 在 C# 中获取两个列表之间的不同列表 - 2

    我有两个字符串列表。如何获取它们之间的不同值列表或从第一个列表中删除第二个列表元素?List<string>list1={"see","you","live"}List<string>list2={"see"}结果应该是{"you","live"}。 最佳答案 在我看来你需要Enumerable.Except():vardifferences=list1.Except(list2);然后你可以遍历差异:foreach(vardifferencei

  6. c# - 为什么 'using' 提高了 C# 性能 - 2

    在大多数情况下,C#编译器似乎可以自动调用Dispose()。像大多数using模式的情况一样:publicvoidSomeMethod(){...using(varfoo=newFoo()){...}//Fooisn'tuseafterhere(obviously)....}因为foo没有被使用(这是一个非常简单的检测)并且因为它没有作为参数提供给另一个方法(这是一个适用于许多用例并且可以扩展的假设),编译器可以自动并立即调用Dispose(),而无需开发人员要求。这意味着在大多数情况下,如果编译器做了一些聪明的工作,using就毫无用处。IDisposable对我来说似乎低

  7. c# - 为什么 C# 使用 implicit void Main? - 2

    我不明白为什么C#的Main函数在默认情况下是无效的(例如在控制台项目中)。在C和C++中,标准明确规定main必须返回int,使用返回值是有意义的,因为我们可以检查来自外部程序的返回值,并查看C/C++应用程序是成功完成还是遇到错误。所以我的问题是:为什么VisualStudio将Main声明为void?一旦C#控制台应用程序执行完毕,向操作系统返回值的最佳方式是什么? 最佳答案 您可以使用int或void作为返回类型。因此,只需更改它并像在C++中那样返回一个值。为了不让新手迷惑,可能默认为void。

  8. c# - 获取两个给定日期之间的所有月份名称 - 2

    这个问题在这里已经有了答案:Listthemonthsbetweentwodates(8个答案)关闭9年前。我正在尝试制作一个函数,它在c#中给出两个日期之间的所有月份名称List<string>liMonths=MyFunction(date1,date2);我的功能是MyFunction(DateTimedate1,DateTimedate2){//somecodereturnlistOfMonths;}你能帮帮我吗

  9. c# - 为什么我们要实现接口(interface)? - 2

    我们为什么要实现,例如ICloneable或IDisposable。我不是在问ICloneable或IDisposable做什么,但我想了解实现这些接口(interface)的充分理由是什么,而不是仅仅编写一个处理或克隆我们的对象的方法? 最佳答案 使用接口(interface)可以使这些功能的使用保持一致。这样,当另一个类想要/需要使用您的类时,它可以将其作为可克隆的一次性对象来使用,而无需担心您的特定实现细节。 关于c#-为什么我们要实现接口(interface)?,我们在Stack

  10. c# - 在 if() 中调用方法 - C# - 2

    我有几个方法会根据它们的成功返回bool值,在IF()内部调用这些方法有什么问题吗?//&&makessurethatMethod2()willonlygetcalledifMethod1()returnedtrue,use&tocallbothmethodsif(Method1()&&Method2()){//dostuffifbothmethodsreturnedTRUE}如果Method1()返回FALSE,Method2()不需要触发。如果上面的代码有任何问题,请告诉我。谢谢。编辑:由于代码没有任何问题,我会接受最有信息的答案...添加评

随机推荐

  1. C# 在 lambda 表达式中声明变量 - 2

    我想像这样做一个简单的lambda表达式:IList<MyEntity1>list=GetSomeList();MyEntity1result=list.SingleOrDefault<MyEntityList>(e=>GetMyEntity2(e)!=null&&GetMyEntity2(e).Id!=null&&GetMyEntity2(e).Id>0);这很完美,但是从MyEntity1获取MyEntity2并不是那么简单,所以我想在lambda表达式中声明一个变量来保存MyEntity2并使用它,而不是一次又一

  2. c# - 如何将图像流嵌入到 MailMessage - 2

    我在将Properties.Resources中的图像嵌入到MailMessage时遇到了一些困难,目前该图像未显示在我收到的电子邮件中。我已经成功地从目录位置嵌入了图像,但如果图像来自内存/应用程序,我会更喜欢。这是我正在做的事情的简化版本。Bitmapb=newBitmap(Properties.Resources.companyLogo);MemoryStreamlogo=newMemoryStream();b.Save(logo,ImageFormat.Jpeg);MailMessagenewEmail=newMailMessage(from,to);newEmail.Subj

  3. c# - 将中值方法添加到列表 - 2

    我想重写C#中的List对象,以便添加像Sum或Average这样的Median方法。我已经找到了这个功能:publicstaticdecimalGetMedian(int[]array){int[]tempArray=array;intcount=tempArray.Length;Array.Sort(tempArray);decimalmedianValue=0;if(count%2==0){//countiseven,needtogetthemiddletwoelements,addthemtogether,thendivideby2intmiddleElement1=tempA

  4. c# - 文件作为附件发送后被锁定 - 2

    我正在发送一个文件作为附件://Createthefileattachmentforthise-mailmessage.Attachmentdata=newAttachment(filePath,MediaTypeNames.Application.Octet);//Addtimestampinformationforthefile.ContentDispositiondisposition=data.ContentDisposition;disposition.CreationDate=System.IO.File.GetCreationTime(filePath);disposit

  5. c# - 如何在不知道封闭泛型类型的情况下访问泛型属性 - 2

    我有一个通用类型如下publicclassTestGeneric<T>{publicTData{get;set;}publicTestGeneric(Tdata){this.Data=data;}}如果我现在有一个对象(来自某个外部源),我知道它的类型是某个封闭的TestGeneric,但我不知道TypeParameterT。现在我需要访问数据我的对象。问题是我无法转换对象,因为我不确切知道哪个关闭的TestGeneric。我用//thxtohttp://stackoverflow.com/questions/457676/c-reflection-check-if-a-c

  6. c# - 获取 double[,] 矩形数组的 double[] 行数组 - 2

    假设你有一个像这样的数组:double[,]rectArray=newdouble[10,3];现在您希望第四行作为3个元素的double[]数组而无需执行以下操作:double[]fourthRow=newdouble[]{rectArray[3,0],rectArray[3,1],rectArray[3,2]};有可能吗?甚至使用Marshal.Something方法?谢谢! 最佳答案 您可以使用Buffer.BlockCopy方法:constintd1=10;constintd2=3;constintdoubleSize=8;

  7. c# - 为什么 C# 设计者要为 'using' 关键字附加三种不同的含义? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭12年前。using关键字具有三种不同的含义:类型/命名空间别名命名空间导入确保调用Dispose的语法糖文档将前两个定义称为指令(我猜这意味着它们本质上是预处理),而最后一个是语句。尽管它们在语法上有所区别,但为什么语言开发人员会通过附加三种不同的含义来使关键字的语义复杂化?例如,(免责声明:在我的脑海中,肯定有更好的例子)为什么不添加像alias和import

  8. c# - 如何证明 Dictionary 的 TryGetValue 的双重检查锁定模式不是线程安全的 - 2

    最近我看到一些C#项目在Dictionary上使用双重检查锁定模式。像这样:privatestaticreadonlyobject_lock=newobject();privatestaticvolatileIDictionary<string,object>_cache=newDictionary<string,object>();publicstaticobjectCreate(stringkey){objectval;if(!_cache.TryGetValue(key,outval)){lock(_lock){if(!_cache.TryGetValue

  9. c# - 有没有一种在 C# 中将结构归零的快速方法? - 2

    这一定已经有人回答了,但我找不到答案:是否有一种快速且提供的方法可以在C#中将struct归零,或者我必须自己提供someMagicalMethod?明确一点,我知道结构将被初始化为0,我想知道是否有一种快速的方法可以将值重置为0。即,structChocolateBar{intlength;intgirth;}staticvoidMain(string[]args){ChocolateBarmyLunch=newChocolateBar();myLunch.length=100;myLunch.girth=10;//Eatingfrenzy...//ChocolateBar.some

  10. c# - 如何动态隐藏jqgrid列 - 2

    我正在我的asp.netMVCweb应用程序中实现jqgrid。在我的网格中,我有两列编辑和删除。只有当用户以admin身份登录时,删除才应该可见。我们如何在jqgrid中动态地hide.show列。我有一个session变量来检查登录用户是否是管理员。我在javascript中访问该变量。但是,不确定如何在jqgrid中隐藏/显示列请帮忙.. 最佳答案 使用此代码,jQuery("#list").jqGrid('hideCol',["colModel1_name","colM