textarea的内容改变,绑定的model却没更新

Doyle

问题描述:

//app.js
angular.module('deapp', [])
.controller('ParentCtrl', ['$scope', ParentCtrl])
.controller('ChildCtrl', ['$scope', ChildCtrl]);

function ParentCtrl($scope) {
  $scope.description = '';
}

function ChildCtrl($scope) {
}

//index.html
<div data-ng-controller="ParentCtrl">
  <div data-ng-controller="ChildCtrl">
    <textarea class="description" data-ng-model="description"></textarea>
  </div>
</div>

我修改textarea的内容时,绑定的description完全没更新,只能用chrome插件ng-inspector看一下。

clipboard.png
图1 初始scope

clipboard.png
图2 输入后ChildCtrl 出现description

所以可以看到问题变成了Angular Scope Inheritance

Angular Scope Inheritance

我用word文档画了scope的继承图示,如下

clipboard.png
图3 初始scope

clipboard.png
图 4 错误的给ChildCtrl添加了description

在这个图可以看到实际上并没有更新父级scope的description,反而在当前所在的ChildCtrl scope新建了description。也就是说与textarea绑定的model实际上是ChildCtrl scope中的description。

$scope的继承是原型链继承,有两个特点:

  1. 读子类的属性时,子类有这个属性(hasOwnProperty)的时候则读子类自己的,子类没有的时候读父类的,不管子类有没有这个属性,在子类上都不会有新属性被创建。

  2. 写子类的属性时,如果子类有这个属性(hasOwnProperty)则写子类的,子类没有的话就会在子类上新建一个同名的新属性,而父类继承过来的属性被隐藏。
    ————来自http://pinkyjie.com/2015/02/07/prototypal-inheritance-of-scope-in-angularjs/

所以对于description也是一样,读description时,先在ChildCtrl中读,读不到就到ParentCtrl中读,所以事先给ParentCtrl的description设置的初始值,在页面刷新后是可以显示出来的。

但是,写description的时候就不一样了,在ChildCtrl中找不到就直接创建一个新的属性,父级scope的同名属性就被隐藏了,textarea绑定的模型也就变成了ChildCtrl scope中的description,往后再怎么修改textarea的内容,父级scope的description永远保持原来的值。

这不是我想看到的,办法是有的,使用.就能解决这个问题了。

  1. 只需改html,将textarea显示绑定到$parent.description

    <div data-ng-controller="ParentCtrl">

     <form data-ng-controller="ChildCtrl">
       <textarea class="description" data-ng-model="$parent.description"></textarea>
     </form>

    </div>

  2. 使用对象的形式来绑定description

    // app.js
    function ParentCtrl($scope) {

     $scope.info = {
       description: '156'
     };

    }

    function ChildCtrl($scope) {
    }

    // index.html
    <div data-ng-controller="ParentCtrl">

     <form data-ng-controller="ChildCtrl">
       <textarea class="description" data-ng-model="info.description"></textarea>
     </form>

    </div>

为什么一个.就能解决问题了呢,以第二个方法为例。
写的时候是写info.description,需要先读info,ChildCtrl没有info,于是去ParentCtrl读,找到info后,就写父级scope的info.description。
Angular Scope Inheritance的详细图文解说

阅读 8.1k

Doyle
linuxer vimer

前端, angular, vue

844 声望
16 粉丝
0 条评论

前端, angular, vue

844 声望
16 粉丝
文章目录
宣传栏