【问题标题】:why ng-model behave unexpectedly in angularjs?为什么 ng-model 在 angularjs 中表现异常?
【发布时间】:2015-05-02 10:56:40
【问题描述】:

我在 Angular js 中举了两个例子,但我得到了意想不到的结果。嵌套控制器的例子:

第一个例子

<div ng-controller="maincontroller">
        <input ng-model="data.name">
         <h1>{{data.name}}</h1>

        <div ng-controller="nestedcontroller">
            <input ng-model="data.name">
             <h1>{{data.name}}</h1>

            <div ng-controller="nestedANOTHERcontroller">
                <input ng-model="data.name">
                 <h1>{{data.name}}</h1>

            </div>
        </div>
      <div ng-controller="nestedOUTERRcontroller">
                <input ng-model="data.name">
                 <h1>{{data.name}}</h1>

            </div>
    </div>

当我在所有嵌套控制器中使用 "data.name" 时。现在,当我更改任何输入字段时,它会反映在所有输入字段和标题字段中。为什么?

其次 当我使用 "name" 而不是 "data.name"

 <div ng-controller="maincontroller">
            <input ng-model="name">
             <h1>{{name}}</h1>

            <div ng-controller="nestedcontroller">
                <input ng-model="name">
                 <h1>{{name}}</h1>

                <div ng-controller="nestedANOTHERcontroller">
                    <input ng-model="name">
                     <h1>{{name}}</h1>

                </div>
            </div>
          <div ng-controller="nestedOUTERRcontroller">
                    <input ng-model="name">
                     <h1>{{name}}</h1>

                </div>
        </div>

当我在顶部输入字段上更改时,它会在所有输入字段和标题字段中更改。但是当我移动到第二个输入字段时,它会更改为它的嵌套(子)输入字段和标题,但不会更改为上级控制器和兄弟控制器为什么?当我移动到最里面的控制器并更改输入字段内的文本时,它会显示标题。现在,如果它的父控制器尝试更改其文本,它就无法做到。父母控制器现在只更改其文本,为什么?

这是我的代码 http://codepen.io/anon/pen/xGGJKR

谢谢

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope ionic-framework


    【解决方案1】:

    这与作用域继承的工作方式有关。有关范围继承细微差别的更全面答案,请阅读此SO answer

    首先,您必须认识到 ng-controller 指令创建的子作用域在原型上继承自父作用域,因此您在此处具有以下层次结构的嵌套作用域(每个作用域的编号为 $ids)

      #2
     /  \
    #5  #3
          \
          #4
    

    因此,当您在第一个 &lt;input&gt; 中键入内容时,它将在 #2 范围内创建 $scope.data = {name: "foo"},并将被所有嵌套范围继承(可见)。另一方面,如果您输入第二个&lt;input&gt; - 那么它将在#3 范围内创建$scope.data(如上),但#2#5 都不会继承它。

    第二点与使用data.namename 时的设置值有关。同样,这与原型继承的细微差别有关。

    ng-model 设置变量data.name 时,它将写入name 属性下继承的data 对象——正如预期的那样——无论data 被定义在哪里。换句话说,data 对象被读取(因此继承的对象被读取),name 属性被写入。

    但是,当ng-model 设置变量name 时,它将直接写入当前作用域的属性name,从而隐藏从父级继承的name 属性。

    正确的做法是:

    1. 始终将点 (.) 表示法与 ng-model(或任何双向绑定属性)一起使用。
    2. 根据您想要的位置定义 data 对象 - 不要将其留给 ng-model 来定义。例如(如果这是意图),在maincontroller 中定义它:

      .controller("maincontroller", function($scope){
         $scope.data = {};
      });
      

      这样做的效果是所有输入都绑定到同一个属性。

    【讨论】:

      【解决方案2】:

      简短的回答是作用域属性的原型继承(不要将作用域用作模型,而是从作用域的某些属性创建对模型的引用)。通常使用服务或工厂或其他提供者定义来存储模型并完成大部分工作,并仅使用控制器使适当的提供者和数据可用于视图。

      https://youtu.be/ZhfUv0spHCY?t=31m12s

      What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        • 2017-11-19
        • 1970-01-01
        相关资源
        最近更新 更多