Javascript 角度是否使用DOM扩散还是必须使用它;“重新渲染”;每一项清单?

Javascript 角度是否使用DOM扩散还是必须使用它;“重新渲染”;每一项清单?,javascript,html,angularjs,dom,reactjs,Javascript,Html,Angularjs,Dom,Reactjs,我不熟悉Angular,但我已经听到(和)一些关于其渲染模型的“谣言”,以及它与其他渲染模型的不同之处 我读过一些Angular专家的帖子,他们声称如果你必须用Angular渲染长列表,可能会很慢,因为Angular会在做出反应(例如)时重新渲染整个列表一旦已呈现,不会从头开始重新呈现整个列表,但它会在内部跟踪呈现的DOM元素,并在新调用时创建新的虚拟DOM,将其与前一个进行比较并仅应用更改 (引自一篇关于角度渲染问题的随机博客文章) 所以当我开始学习Angular时,我的第一件事就是尝试这个

我不熟悉Angular,但我已经听到(和)一些关于其渲染模型的“谣言”,以及它与其他渲染模型的不同之处

我读过一些Angular专家的帖子,他们声称如果你必须用Angular渲染长列表,可能会很慢,因为Angular会在做出反应(例如)时重新渲染整个列表一旦已呈现,不会从头开始重新呈现整个列表,但它会在内部跟踪呈现的DOM元素,并在新调用时创建新的虚拟DOM,将其与前一个进行比较并仅应用更改

(引自一篇关于角度渲染问题的随机博客文章)

所以当我开始学习Angular时,我的第一件事就是尝试这个

我似乎无法重现这个问题

这是一个虚拟的Plunker,我想复制这个问题

您可以将新项目添加到消息列表中,该列表使用ng repeat呈现,如下所示:

<table>
  <tr ng-repeat="m in messages" class="{{name}}">
    <td>{{m.message}}</td>
    <td>{{m.date}}</td>
  </tr>
</table>

{{m.message}}
{{m.date}
您可以单击一个按钮来更新一个这样的项目,还可以更新另一个与列表完全无关的属性(
name

现在,如果我打开开发者工具栏,在表中修改一个项目的HTML属性,然后单击“添加新消息”,我的修改不会丢失或被Angular覆盖-Angular似乎没有完全重新呈现DOM。这看起来相当聪明

Angular最近开始使用DOM diffing了吗?(我的演示使用Angular 1.4.0测试版)

因为从DOM渲染的角度来看,我看不出React和Angular之间有多大区别


你能给我一个用例来说明Angular的渲染模型的缺点吗?

关于这个主题有很多困惑,主要是因为它不是一个简单的“Angular re-rendering everything”类型的答案

角度数据绑定的基础(在1.x版本中)围绕着
$digest
循环的概念,而
$scope
$scope
是一个特殊的对象,它“自跟踪”它的属性,并使用
$scope.$watch()方法为每个属性创建一个JavaScript事件监听器
。这些侦听器监视HTML中可更改的输入元素以及
$scope
属性的更改

每当启动任何JavaScript侦听器时,
$digest
循环遍历
$watch
下的每个项目,并相应地更新值。您还可以调用
$scope.$apply()
手动执行
$digest
循环。此循环可以执行多次,因为对一个值的更改可能会影响
$watch
下的另一个值,从而触发另一个
$digest
$digest
循环确实有一个迭代上限,以确保它在循环引用时停止

当处理对象数组时,会出现摩擦,特殊指令
ng repeat
。默认情况下,
$watch()
函数仅检查对象引用的相等性。在每个
$digest
中,AngularJS将检查新旧值是否相同对象,并且仅当您实际更改基础对象引用时才会调用其处理程序

为了解决这个问题,
ng repeat
创建了它自己独特的
范围
。这允许对数组中的每个元素使用唯一的
$watch
。这里的挑战是,如果数组本身发生更改,则会重新生成此唯一的
范围
,以及所有
$watch
元素。推、弹出、拼接数组可以创建许多
$watch

Angular提供了一些处理此问题的方法

1.3中添加的新Bind-Once语法允许侦听器只存在于表达式计算之前
ng repeat=“element in::elements”
将遍历数组,填充DOM,然后销毁事件侦听器。这非常适合于DOM元素在计算后不发生更改的情况

也可以使用
track by
积极跟踪元素
ng repeat=“element in elements track by$id”
将在唯一的
$id
值上创建一个
$watch
,而不是元素在数组中的位置。这允许更稳定的
$watch
传播,在元素值可能发生变化的情况下非常理想


至于为什么您在控制台中所做的更改没有丢失:首先,开发人员控制台中的更改不会触发任何事件侦听器。其次,只有当
$watch
检测到更改时,才会修改您更改的特定DOM元素。然而,这并不是HTML的真正区别;Angular不是“查看HTML”,可以说是“查看数据”。

这对我来说并不“太宽泛”。OP问的主要问题是关于角度的一个特定机制。你的问题有点宽泛,因为它确实会问几个问题,可能更适合程序员。无论如何,Angular并不像React那样有差异,但ng repeat确实跟上了它正在重复的内容和相关的元素。它只会改变需要改变的东西。请参见
ng repeat
跟踪方式
选项。Angular在这方面的跟踪效率就是为什么在
ng repeat
中不允许重复,除非您使用
track by
选项来更改Angular的监视内容以保持同步。调查对某些技术提出未经证实的声明的博客帖子的真实性并不是我们的专长,这也不是程序员的专长。这是一个完全可以回答的问题。答案将概述在摘要循环中实现更改所采取的步骤,以及为什么