为什么 ng-if 在 angularjs 中造成这么多问题

Why ng-if creates so much issue in angularjs

今天遇到一个很奇怪的问题,想弄明白为什么会这样
下面是我的 html

<div class="partial-container workflow-cont" ng-if="true">
<div class="clearfix mb20">
        <h3 class="heading-text pull-left pointer" ng-click="resetRole()" >{{'Roles' | translate}}</h3>
    </div>
    <div class="inner-container blue-border clearfix relative no-padding" ng-if="true">
        <div class="role-left-nav pull-left">
    .
    .
    .
    Some other html
    .
    .
    .
    <div class="any-or-select pull-none clearfix valign-middle">
    <p>
       <input type="radio" name="choice_p" id="low" ng-model="defineChoice" value="0" >
       <label for="low" class="ng-binding">{{'Absolute' | translate}}</label>
    </p>
    <p>
       <input type="radio" name="choice_p" id="medium" ng-model="defineChoice" value="1" >
       <label for="medium" class="ng-binding">{{'Attributes' | translate}}</label>
    </p>
    <p>
       <input type="radio" name="choice_p" id="high" ng-model="defineChoice" value="2"  >
       <label for="high" class="ng-binding">{{'Rule' | translate}}</label>
    </p>
  </div>

现在,当我单击单选按钮时,模型 defineChoice 的值已成功更改。
但是当我尝试从控制器做同样的事情时 $scope.defineChoice = 0 它的值没有变回来,但是当我从控制器执行 console.log 时,它变为零但没有反映在视图中。

但是当我从视野中的任何地方删除 ng-if="true" 时,一切都很好! 这是因为 ng-if 创建了一个子范围,但如果是这样,那么为什么它在 init 时第一次工作但后来变坏了。

ng-if 创建一个子范围,因此 ng-if 中的 ng-model 指令绑定到新范围。要访问父作用域,请使用 ng-model="$parent.defineChoice".

在 Angular 中,模型存在于作用域中,模型绑定依赖于涉及原型作用域继承的作用域解析算法。如果一个模型绑定解析为同一个模型,无论范围如何,那么对模型的任何更改都会影响所有绑定。这称为双向模型绑定:对模型的更改会影响视图,而对视图的更改会影响模型。

现在,双向模型绑定在模型为只读时按预期工作。但如果不是,通常是因为您绑定到原语,使用带有可写控件的 ngModel(即 ngModel 和单选按钮),并且还涉及子范围(即 ngIf);一旦写入模型,双向模型绑定就会中断。写入模型时,它会在子作用域中创建一个与父作用域中的模型同名的模型。您现在拥有模型的两个副本,它们可以彼此独立运行。

你是怎么解决的?

将 ngModel 绑定到对象在范围内的 属性 - 不要绑定到范围内的原语。

ng-model="someObj.defineChoice"

有时这也称为 "always have a dot in your ngModel" 经验法则,这并不总是必要的,但却是一个很好的指导方针。

someObj 被解析时,它会在正确的范围内正确解析引用(通过原型范围继承),然后绑定到该引用的 属性。重要的一点是,每个模型绑定都解析相同的模型,因此即使写入模型,双向模型绑定也能正常工作。