关于 AngularJS 中子控制器访问父控制器中元素的正确方法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
shiltian
V2EX    程序员

关于 AngularJS 中子控制器访问父控制器中元素的正确方法

  shiltian
shiltian 2017-01-15 17:09:01 +08:00 5956 次点击
这是一个创建于 3194 天前的主题,其中的信息可能已经有所发展或是发生改变。

假设我在父控制器中放置一个 Bootstrap 风格的 alert 框,用于提示错误,类似如下效果: !()[https://ww1.sinaimg.cn/large/006tKfTcjw1fbrff61vqcj308q03pglq.jpg]

<body ng-cOntroller="ParentController as parentCtrl"> <!-- 这里有一个 alert ,用于显示错误 --> <div ng-show="parentCtrl.alert"></div> <div ng-cOntroller="ChildController as childCtrl"> </div> </body> 

在 js 文件中,我在控制器 ParentController 中定义了变量 alert

app.controller('ParentController', [function() { var self = this; self.alert = null; }]); app.controller('ChildController', [function() { // 那么这里应该如何访问到 ParentController 中的 alert 呢? }]); 

现在我想做的,是当 ChildController 中某些操作出现错误的时候,给 ParentController 中的 alert 赋值,这样那个错误 alert 框就可以显示,不知道应该如何写 ChildController 的代码呢?

现在有一个折中的办法是,将 ParentController 中的 alert 元素绑定到 $scope 中,即如下:

<body ng-cOntroller="ParentController as parentCtrl"> <!-- 这里有一个 alert ,用于显示错误 --> <div ng-show="alert"></div> <div ng-cOntroller="ChildController as childCtrl"> </div> </body> 

相应的 js 文件如下:

app.controller('ParentController', ['$scope', function($scope) { $scope.alert = null; }]); app.controller('ChildController', ['$scope', function($scope) { $scope.alert = { type: 'alert', info: 'Error...' }; }]); 

但是现在的 AngularJS 不都推崇的是直接将要显示的数据绑定到控制器上,而不是向控制器中注入 $scope 变量。因此想请教一下大家正确的方法,或者是在单页面应用中,如何正确地显示错误框。

6 条回复    2017-01-16 19:22:38 +08:00
alibabamama
    1
alibabamama  
   2017-01-15 20:00:42 +08:00
我也又遇到过类似的问题,用的`yeoman`生成的一套系统,所以整个架构和写法上和你贴出来的有点不同。我在 child state 通过$scope, 类似 `$scope.ParentController.alert`的形式去获取和更新的。
gyteng
    2
gyteng  
   2017-01-15 20:46:51 +08:00
绑定到$scope 是一种方法,还可以自己写一个 service 来搞定多个 controller 之间共享数据的问题
shiltian
    3
shiltian  
OP
   2017-01-16 07:17:16 +08:00 via iPhone
@gyteng 诶?写给 service 如何来共享数据呀?我能想到的只是单向传递,如果 service 里面的值变了,如何保证 controller 的值也跟着改变呀?
WittBulter
    4
WittBulter  
   2017-01-16 07:39:30 +08:00 via iPhone
手机写了一堆,忘了保存,待会换电脑来写。
WittBulter
    5
WittBulter  
   2017-01-16 16:21:30 +08:00   2
这是典型的父子通信问题,但是并不符合你的业务逻辑。
在 NG1 中,如果真的要使用父子通信,最优雅的办法是采用一个共享的服务来解决,当有涉及模板时,应创建一个指令,任何子控制器都通过相应的事件来触发指令。使用共享作用域的 scope 的方法实际上不好的,你代码中的父级作用域其实就是类似 rootScope ,当他们被越来越多的变量、对象占有时,很难通过控制器之间的切换累释放内存。其次当你需要调用他们的时候也会很难,特别是你的控制器代码被复用时,其他人很难知道需要在父级再做一件这样的事。这就违背了 NG1 中自治的哲学。

如果要达到这一点,至少要保证你的任何控制器不依赖于其他控制器,任何指令可以直接使用而无需在控制器中为它准备一些元数据,任何服务也是注入即使用。这其实是很难的,因为你要做一些额外的工作来达到这一点,比如强制自己不使用非当前作用域的变量、函数,通信采用服务与事件等等。但是它们带来的好处也显而易见。

业务逻辑中, Alert 这样的问题常常会带有一个基础的模板,我建议是将它包装成一个指令,使用 Alert 相应模板,然后在较高层作用域的模板中编译(让子作用域都可以享受),当你需要它显示时,在控制器中发出相应的事件来触发这个模板显示与隐藏。
还有一种更优雅的解决方案,新建一个 alertModule ,将控制器、指令、服务全部挂载在 alertModule 上,再让业务的 module 依赖它,即可以使用相应的方法来触发这个弹窗模块。

你可以参考一下我写的两个模板,它们分别是挂载 window 和挂载 module 方式。
https://github.com/WittBulter/sendAlert
https://github.com/WittBulter/angular-mobile-tips
angular-mobile-tips 使用了很多有意思的技巧,是一个典型的 NG1 插件,可以尝试模仿它写一个。
shiltian
    6
shiltian  
OP
   2017-01-16 19:22:38 +08:00
@WittBulter 非常感谢,我先研究一下你给的那两个模版。
关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4281 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 27ms UTC 04:09 PVG 12:09 LAX 21:09 JFK 00:09
Do have faith in what you're doing.
ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86