首页 >web前端 >js教程 >原型继承如何与 AngularJS 作用域中的双向数据绑定一起工作?

原型继承如何与 AngularJS 作用域中的双向数据绑定一起工作?

Susan Sarandon
Susan Sarandon原创
2024-12-26 11:51:10730浏览

How Does Prototypal Inheritance Work with Two-Way Data Binding in AngularJS Scopes?

AngularJS 中范围原型/原型继承的细微差别是什么?

快速回答:

子作用域通常继承自其父作用域,但并非总是如此。此规则的一个例外是范围为 { ... } 的指令——这会创建一个不典型继承的“隔离”范围。在创建“可重用组件”指令时经常使用此构造。

关于细微差别,范围继承通常很简单......直到您需要双向数据绑定(例如,表单elements, ng-model) 在子作用域中。如果您尝试从子作用域内绑定到父作用域中的基元(例如数字、字符串、布尔值),ng-repeat、ng-switch 和 ng-include 可能会让您陷入困境。它并不像大多数人期望的那样工作。子作用域拥有自己的属性,该属性隐藏/隐藏同名的父属性。您的解决方法是:

  1. 在模型的父级中定义对象,然后在子级中引用该对象的属性:parentObj.someProp
  2. 使用 $parent.parentScopeProperty (并不总是可能,但比 1 更容易。如果可能的话)
  3. 在父作用域上定义一个函数,并从子作用域中调用它(不是总是可能的)

新的 AngularJS 开发人员通常没有意识到 ng-repeat、ng-switch、ng-view、ng-include 和 ng-if 都会创建新的子作用域,所以问题当涉及到这些指令时经常会出现。 (请参阅此示例以快速说明问题。)

通过遵循始终使用“.”的“最佳实践”,可以轻松避免原语的此问题。在您的 ng-models 中 – 观看 3 分钟。 Misko 演示了 ng-switch 的原始绑定问题。

有一个“.”在您的模型中将确保原型继承发挥作用。所以,使用:

L-o-n-g 答案:

理解原型继承

在讨论范围继承之前了解原型继承非常重要。

假设parentScope 具有属性aString、aNumber、anArray、anObject 和aFunction。如果childScope原型继承自parentScope,我们有:

[原型继承图的图像]

如果我们尝试从子作用域访问parentScope上定义的属性,JavaScript将首先查找在子作用域中,找不到该属性,然后在继承作用域中查找,并找到该属性。 (如果它在父作用域中没有找到该属性,它将沿着原型链继续向上......一直到根作用域)。所以,这些都是真的:

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

假设我们这样做:

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

不参考原型链,并在 childScope 中添加一个新的 aString 属性。这个新属性隐藏/隐藏了同名的parentScope属性。当我们下面讨论 ng-repeat 和 ng-include 时,这一点将变得非常重要。

[属性隐藏图的图像]

假设我们这样做:

childScope.aString = 'child string'

由于在 childScope 中未找到对象(anArray 和 anObject),因此查阅了原型链。在parentScope 中找到对象,并在原始对象上更新属性值。 childScope 中没有添加新属性;没有创建新对象。 (请注意,在 JavaScript 中数组和函数也是对象。)

[遵循原型链图的图像]

假设我们这样做:

childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'

不参考原型链,子作用域获取两个新的对象属性,这些属性隐藏/隐藏具有相同名称的父作用域对象属性。

[Image更多属性隐藏图]

Angular 作用域继承

竞争者:

  • 原型继承:ng-重复、ng-include、ng-switch、ng-controller、指令范围: true,指令包含:true。
  • 隔离范围:指令范围:{ ... }。这会创建一个“隔离”作用域。

默认情况下,指令不会创建新作用域(即,scope: false)。

ng-include

假设我们的控制器中有:

childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }

并且在我们的 HTML 中:

$scope.myPrimitive = 50;
$scope.myObject = {aNumber: 11};

每个 ng-include 都会生成一个新的子作用域,其原型继承自父作用域。

[ng-include 子作用域图的图像]

在第一个输入文本框中键入(例如“77”)会导致子作用域获得一个新的 myPrimitive 作用域属性,该属性隐藏/隐藏同名的父作用域属性。

[带有原始图的 ng-include 图像]

在第二个输入文本框中键入(例如“99”)不会产生一个新的子属性。因为 tpl2.html 将模型绑定到对象属性,所以当 ngModel 查找对象 myObject 时,原型继承就会启动——它在父作用域中找到它。

[带有对象图的 ng-include 图像]

如果我们不想将模型从原始模型更改为原始模型,我们可以重写第一个模板以使用 $parent object:

<script type="text/ng-template">

在此输入文本框中键入(例如“22”)不会产生新的子属性。该模型现在绑定到父作用域的属性(因为 $parent 是引用父作用域的子作用域属性)。

[ng-include 与 $parent 图的图像]

ng-开关

NG-switch 作用域继承的工作方式与 ng-include 类似。因此,如果您需要与父作用域中的原语进行 2 路数据绑定,请使用 $parent,或将模型更改为对象,然后绑定到该对象的属性。这将避免子作用域隐藏/隐藏父作用域属性。

ng-repeat

NG-repeat 的工作方式略有不同。假设我们的控制器中有:

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

并且在 HTML 中:

childScope.aString = 'child string'

对于每个项目/迭代,ng-repeat 创建一个新范围,其原型继承自父级作用域,但它还会将项目的值分配给新子作用域上的新属性(新属性是循环变量名称)。以下是 ng-repeat 的 Angular 源代码实际内容:

childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'

如果该项是基元(如 myArrayOfPrimitives 中),则本质上会将值的副本分配给新的子作用域属性。更改子作用域属性的值(即使用 ng-model,因此使用子作用域 num)不会更改父作用域引用的数组。因此,在上面的第一个 ng-repeat 中,每个子作用域都会获得一个独立于 myArrayOfPrimitives 数组的 num 属性:

[带有基元图的 ng-repeat 图像]

这个 ng-repeat不会起作用(就像你想要/期望的那样)。在文本框中键入内容会更改灰色框中的值,这些值仅在子范围中可见。我们想要的是输入影响 myArrayOfPrimitives 数组,而不是子范围基元属性。为了实现这一点,我们需要将模型更改为对象数组。

因此,如果该项目是一个对象,则将对原始对象(而不是副本)的引用分配给新的子作用域财产。更改子作用域属性的值(即使用 ng-model,因此使用 obj.num)确实会更改父作用域引用的对象。因此,在上面的第二个 ng-repeat 中,我们有:

[带有对象图的 ng-repeat 图像]

(我将一条线涂成灰色,以便清楚地显示在哪里)它正在运行。)

这按预期工作。输入

以上是原型继承如何与 AngularJS 作用域中的双向数据绑定一起工作?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn