ionic中数据双向绑定无效的问题,angularjs作用域的问题

ionic中数据双向绑定无效的问题,angularjs作用域的思考

angular的数据双向绑定机制,让我们在开发SPA时,非常的方便。但是,今天在开发一个ionic项目时,确遇到这么个问题:

在路由代码中定义了一个首页的路由,对应controller:homeCtrl。

1
2
3
4
5
6
7
8
9
.state('toys.index', {
url: '/index',
views: {
'toys-index': {
templateUrl: "template/index.html",
controller: 'homeCtrl'
}
}
})

加载的模板文件如下,其中在ion-content中有一个绑定了双向数据的输入框。

1
2
3
4
5
6
7
8
9
10
11
12
13
<ion-view view-title="indexs" hide-nav-bar="true">
<ion-header-bar class="bar-dark" align-title="center">
</ion-header-bar>
<ion-content ng-controller="homeCtrl">
<div class="item item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="搜索" ng-model="keywords">
</label>
<button class="button button-small ion-ios-search-strong" ng-click="search()">
</button>
</div>
</ion-content>
</ion-view>

在controller中定义了keywords和search函数

1
2
3
4
$scope.keywords = "";
$scope.search = function(){
$state.go("search",{keywords:$scope.keywords});
}
方法一

按照angular的双向绑定原则,我在输入框中输入字符,$scope.keywords也应该同时改变,但是点击按钮调用函数,获取到的keywords永远都是空。后来根据知乎上找到的答案,代码改成如下:

1
2
3
4
5
$scope.data={};
$scope.data.keywords = "";
$scope.search = function(){
$state.go("search",{keywords:$scope.data.keywords});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
<ion-view view-title="index" hide-nav-bar="true">
<ion-header-bar class="bar-dark" align-title="center">
</ion-header-bar>
<ion-content ng-controller="homeCtrl">
<div class="item item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="搜索" ng-model="data.keywords">
</label>
<button class="button button-small ion-ios-search-strong" ng-click="search()">
</button>
</div>
</ion-content>
</ion-view>

把keywords放在data对象中,一试还真的起作用了。

方法二

还有另外一种方法,不用到data对象,只需要把路由定义中的controller去掉,直接在模板文件中的ion-content上显示声明ng-controller=”homeCtrl”,这样之前的代码就能起作用。

思考

问题虽然是解决了,但是为什么在ionic中会出现这种问题呢?

后仔细学习了徐飞大神的angular作用域文章,醍醐灌顶,豁然开朗,学习angular的同学一定要好好拜读,参考地址 根据这篇文章中介绍的作用域知识,我大概猜测ionic产生双向数据绑定失效的原因应该是:

首先,在ionic路由中定义了模板文件的controller后,ionic会在加载模板文件后,在模板文件的最顶级dom上(也就是ion-view)创建你的controller作用域$scope,然后由于ionic在我页面上的ion-content没有找到我显示声明的ng-controller,所以他会自动创建了一个匿名的作用域$scope2(这里我认为是ionic的内部机制会在ion-content上默认创建一层作用域,并没有真的研究过),那么因为我的controller中定义了keywords,实际上这里是$scope.keywords,但是页面上实际显示的其实是$scope2.keywords,这个值并没有定义,根据angular的作用域继承关系,$scope2.keywords= $scope.keywords,当我改变该值的时候,变化的是$scope2.keywords,但是这时候$scope.keywords这个值是并没有变化的。所以我在controller里面获取的$scope.keywords没有变化。

那么为什么按上面2种方法修改可以解决这个问题呢?

首先当我把keywords改成了data.keywords后,$scope2继承的就是是$scope的data对象,而熟悉js的同学都知道,修改$scope2.data对象中的引用则$scope.data也会改变,所以这种方法可以使2层作用域中的值同时改变,在controller中获取到的值就是界面上一样的值了。

第二种方法去掉了路由中定义的controller,直接写在模板中的ion-content上,这样模板文件加载进来后,就只有ion-content上的一层作用域了,双向数据绑定当然就起作用了。(如果ng-controller写在模板文件的ion-view上,依然是没用的,所以我猜想ionic是会自动在ion-content上创建作用域)

原文地址