所有angularjs 控制器器都放在controllers.js中会有什么影响

AngularJS控制器controller正确的通信的方法_javascript_ThinkSAAS
AngularJS控制器controller正确的通信的方法
AngularJS控制器controller正确的通信的方法
内容来源: 网络
AngularJS是一款非常强大的前端MVC框架,AngularJS中的controller是个函数,用来向视图的作用域($scope)添加额外的功能,我们用它来给作用域对象设置初始状态,并添加自定义行为。
当我们在创建新的控制器时,angularJS会帮我们生成并传递一个新的$scope对象给这个controller,在angularJS应用的中的任何一个部分,都有父级作用域的存在,顶级就是ng-app所在的层级,它的父级作用域就是$rootScope。
每个$scope的$root指向$rootScope, $cope.$parent指向父级作用域。
cotroller之间的通信本质上是当前的controller所在的$scope如何跟其他controller上的$scope进行通信。
通常有3中解决方式:
利用作用域继承的原理,子控制器访问父级控制器中的内容。 使用angularJS中的事件,也就是使用$on,$emit,$broadcast进行消息传递 使用angularJS中的服务
第一种方式
即作用域嵌套作用域,有一定的使用限制,需要作用域嵌套起来,在实际开发中这种场景相对比较少,但也不是没有,这种方式更简单直接。
angularJS中默认情况下,当前作用域中无法找到某个属性时,就会在父级作用域中进行查找,若找不到直至查找到$rootScope。 如果在$rootScope中也无法找到程序依旧运行,但视图不会更新。
javascript
//Javascript
app.controller(&ParentController&, function($scope) { 
$scope.person = {greeted: false};
app.controller(&ChildController&, function($scope) {
$scope.sayHello = function() {
$scope.person.name = &Ari Lerner&;
//HTML
&div ng-controller="ParentController"&
&div ng-controller="ChildController"&
&a ng-click="sayHello()"&Say hello&/a&
&/div&
{{ person }}
&/div&
//result
{"greeted":true, "name": "Ari Lerner"}
第二种方式
因为作用域是有层次的,所以可以利用作用域链传递事件。
传递事件有2种方式: * $broadcast: 触发的事件要通知整个事件系统(允许任意作用域处理这个事件)就要向下传播。 * $emit: 如果要提醒一个全局模块,需要通知更高层次的作用域时(例如$rootscope)需要把事件向上传递。
作用域上使用$on进行事件监听。
JavaScript
app.controller(&ParentController&, function($scope) { 
$scope.$on(&$fromSubControllerClick&, function(e,data){
console.log(data); // hello
app.controller(&ChildController&, function($scope) {
$scope.sayHello = function() {
$scope.$emit(&$fromSubControllerClick&,&hello&);
//HTML
&div ng-controller="ParentController"&
&div ng-controller="ChildController"&
&a ng-click="sayHello()"&Say hello&/a&
&/div&
&/div&
在这里想要说的另外一个问题就是事件传播的性能问题,$broadcast+$on的方式回通知所有的子作用域,这里就会有性能问题,所以推荐使用$emit+$on的方式,为了进一步提升性能,定义的事件处理函数要在作用域销毁时一起释放掉。
使用$emit+$on的方式需要我们将事件监听绑定在$rootScope上,例如:
JavaScript
angular
.module(&MyApp&)
.controller(&MyController&, [&$scope&, &$rootScope&, function MyController($scope, $rootScope) {
var unbind = $rootScope.$on(&someComponent.someCrazyEvent&, function(){
console.log(&foo&);
$scope.$on(&$destroy&, unbind);
但是这种方式有点繁琐,定义多个事件处理函数时整个人都不好了,所以我们来改进一下
利用装饰器来定义一个新的事件绑定函数:
JavaScript
angular
.module(&MyApp&)
.config([&$provide&, function($provide){
$provide.decorator(&$rootScope&, [&$delegate&, function($delegate){
Object.defineProperty($delegate.constructor.prototype, &$onRootScope&, {
value: function(name, listener){
var unsubscribe = $delegate.$on(name, listener);
this.$on(&$destroy&, unsubscribe);
enumerable: false
return $
那么我们在控制器中定义事件处理函数时:
JavaScript
angular
.module(&MyApp&)
.controller(&MyController&, [&$scope&, function MyController($scope) {
$scope.$onRootScope(&someComponent.someCrazyEvent&, function(){
console.log(&foo&);
个人强烈推荐此种做法
第三种方式
利用angularJS中service单例模式的特性,服务(service)提供了一种能在应用的整个生命周期内保持数据的方式,能够在控制器之间进行通信,且能保证数据的一致性。
一般我们都会封装server来为应用提供访问数据的接口,或者跟远程进行数据交互。
JavaScript
var myApp = angular.module("myApp", []);
myApp.factory(&Data&, function() {
return {
name: "Ting"
myApp.controller(&FirstCtrl&, function($scope, Data) {
$scope.data = D
$scope.setName = function() {
Data.name = "Jack";
myApp.controller(&SecondCtrl&, function($scope, Data) {
$scope.data = D
$scope.setName = function() {
Data.name = "Moby";
以上所述是针对AngularJS控制器controller正确的通信的方法,希望能够帮助到大家。
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信投放本站广告请联系:
Sencha相关书籍
在Ext JS 5中使用ViewControllers
Posted 周日, 06/22/2014 - 14:52 by
在Ext JS 5中,在应用程序架构方面提供了一些令人兴奋的改进,如添加了ViewModels、MVVM以及viewControllers来加强MVC应用程序。最重要的是,这些选择并不互斥,因此,可以采用增量的方式来介绍这些功能,又或者将他们混合在一起。
在Ext JS 4,控制器就是一个从Ext.app.Controller的派生的类。这些控制器会使用类似CSS选择器(称为组件查询)来查找组件并对他们的事件做出响应。还可以使用refs来选择或返回组件实例。
这些控制器会在应用程序启动时被创建,且会存在于整个应用程序的生命周期。在控制器的生命周期内,控制器所关注视图可以说是来了又去。甚至可能是一个控制器管理着很多实例。
对于大型应用程序,这技术可能会遇到某些挑战。
在这种环境中,视图和控制器可能是由多个开发团队开发并继承到最终的应用程序的。为来确保控制器只对他们关注的视图做出响应将会是一项艰难的工作。此外,对于开发人员来说,通常都会希望在应用程序启动时限制控制器创建的数量。虽然可以通过努力延迟控制器的创建,但是他们不能被销毁,因此在他们不再需要的时候仍然会保持在内存中。
虽然Ext JS 5能向后兼容这些控制器,但它引入了一种新型的控制器,可设计来处理这些挑战: Ext.app.ViewController。ViewController通过以下方式来实现操作:
简化视图的listeners和reference配置项的使用
利用视图的生命周期来自动管理他们相关的ViewController
基于一对一来关联管理视图以降低ViewController的复杂度
提供封装以使嵌套视图更可靠
为相关视图之上的任何层保留选择组件和监听他们事件的能力
配置项listeners虽然不是新的,但是在Ext JS 5为它添加了新的能力。新的listeners功能会在未来的文章《Declarative Listeners in Ext JS 5》中进行全面的探讨。针对ViewControllers,我们来看两个示例。第一个是最基本的,在视图的子组件中使用listeners配置项:
Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo',
xtype: 'textfield',
fieldLabel: 'Bar',
listeners: {
change: 'onBarChange'
// no scope given here
Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo',
onBarChange: function (barTextField) {
// called by 'change' event
在上面代码的listeners中,使用了一个命名事件句柄(onBarChange),但没有指定作用域(scope)。在事件系统内部,会将Bar文本字段的作用域解析为其所属的ViewController。
在过去,listeners配置项会预留给组件的创建者使用,那么,如何让视图去监听自己的事件呢,而且又可以让它的基类来触发呢?解决之道就是使用显式的作用域:
Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo',
listeners: {
collapse: 'onCollapse',
scope: 'controller'
以上示例代码利用了两个Ext JS 5的新功能:命名的作用域和声明性监听。在这里的重点是命名的作用域。在这里可使用两个有效的作用域命名:this和controller。在写MVC应用程序的时候,基本上总是会使用controller,这不用说指的就是视图的ViewController(不是创建视图实例的那个视图的ViewController )。
由于视图是ponent的一种类型,因而可为它定义一个xtype,以便其他视图以相同的方式来创建创建视图实例及其文本字段。为了探讨如何将这些整合在一起,考虑一下如何使用改视图,例如:
Ext.define('MyApp.view.bar.Bar', {
extend: 'Ext.panel.Panel',
xtype: 'bar',
controller: 'bar',
xtype: 'foo',
listeners: {
collapse: 'onCollapse'
在这种情况下,Bar视图创建了Foo视图的一个实例作为它的一个子组件。此外,还为Foo视图绑定了collapse事件。在之前版本的Ext JS或Sencha Touch,这些声明将会产生冲突,而在Ext JS 5,正如预期的那样得到了解决。通过Foo视图声明的监听只会在Foo的ViewController内触发,而在Bar视图声明的监听只会在Bar的ViewController内触发。
在编写控制器逻辑的时候,最烦的就是需要获取所需的组件来完成只能的操作,例如:
Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo',
xtype: 'button',
text: 'Add',
handler: 'onAdd'
xtype: 'grid',
Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo',
onAdd: function () {
// ... get the grid and add a record ...
现在应该如何起获取网格组件?在Ext JS 4,可以使用refs配置项或者一些其他方式来寻找组件。所以这些技术都要求在网格上放置一些可用来识别且能唯一标识网格的属性。老技术会使用id配置项(Ext.getCmp)或者itemId(适用于refs或一些组件查询语法)配置项。使用id的优势是可实现快速查找,但必须确保这标识在整个应用程序或DOM中是唯一的,该方法并不可取。使用itemId或其他一些查询会更灵活,但这需要执行搜索来寻找所需的组件。
在Ext JS 5可以使用新的reference配置项来实现,只需要添加reference到网格并使用lookupReference就可以来获取它:
Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo',
xtype: 'button',
text: 'Add',
handler: 'onAdd'
xtype: 'grid',
reference: 'fooGrid'
Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo',
onAdd: function () {
var grid = this.lookupReference('fooGrid');
这类似于分配了一个名为fooGrid的itemId并执行“this.down('#fooGrid')”。不过,这在底层的实现是不同的,而且区别很大。首先,reference配置项会将组件自身注册到它所属的视图(通常是ViewController中标识)。其次,lookupReference方法只去查询缓存以确定是否需要刷新引用(指的是容器的add或remove操作)。如果一切顺利,就可从缓存中返回引用。另外,伪代码如下:
lookupReference: (reference) {
var cache = this.
if (!cache) {
Ext.fixReferences(); // fix all references
cache = this. // now the cache is valid
return cache[reference];
也就是说,这样就不需要搜索且不会由于是一次成型的,会因容器的添加或删除子组件而出现问题。正如所看到的,这样的好处就是提供了效率。
虽然在Ext JS 4种使用选择器的实现非常灵活,但同时也存在一定的风险。事实上,这些选择器可以“看到”所有的组件层次结构,既强大也容易出现错误。例如,一个控制器在隔离运行时可以运转正常,但一旦引入了其他视图,就可以会失败,原因是它的选择器可能会意外的匹配了新的视图。
这些问题可通过以下做法来进行管理,不过,当在ViewController中使用listeners或references时,要解决这些问题就变得不可能了。这是因为listeners和references配置项只能连接他们所属的ViewController。在视图内部,可以使用任意唯一的reference值,因为视图知道这些名字不会曝露给视图的创建者。
同样,listeners也可以保留给它所属的ViewController而不会意外的分发到其它使用错误的选择器的控制器的事件处理中。虽然监听会优先于选择器,但在需要以选择器为基础的时候,这两种机制可以一起工作。
要实现这个,视图需要通过它所属视图的ViewController来触发事件。在ViewController有一个辅助方法可以用了实现这个:fireViewEvent,例如:
Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo',
onAdd: function () {
var record = new MyApp.model.Thing();
var grid = this.lookupReference('fooGrid');
grid.store.add(record);
this.fireViewEvent('addrecord', this, record);
在视图的创建者可使用标准形式的监听:
Ext.define('MyApp.view.bar.Bar', {
extend: 'Ext.panel.Panel',
xtype: 'bar',
controller: 'bar',
xtype: 'foo',
listeners: {
collapse: 'onCollapse',
addrecord: 'onAddRecord'
在Ext JS 4.2,MVC事件分发会被一般化为对事件域的引用。事件域会在事件触发时截获事件并将他们分发到由选择器匹配所控制的控制器中。尽管其他域只有有限的选择器,但组件事件域具有完整的组件查询选择器。
在Ext JS 5,每一个ViewController会创建一个名为view的新的事件域的实例。该事件域允许ViewController去使用标准的隐式的限制了它的作用域为所属视图的listen或control方法。它还添加了一个特定的选择了来匹配视图自身。
Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo',
control: {
// matches the view itself
collapse: 'onCollapse'
click: 'onAnyButtonClick'
从以上代码可以看出listeners和选择器之间的区别。选择器button可匹配视图及子视图(不论深度,即使是是重孙视图)中的任何按钮,也就是说,基于选择器的处理不会理会封装边界,改行为与以前的Ext.app.Controller的行为是一致的,在有限的情况下这是很实用的技术。
最后,事件域会遵循嵌套并有效的将事件依照视图层次往上冒泡,也就是说,当一个事件触发时,它首先会传递到任何标准的listeners中。然后,它会传递到它所属的ViewController,接着通过它的父ViewController(如果存在)传递到最顶层。最终,事件会被传递到标准的组件事件域,以便由Ext.app.Controller派生的控制器处理。
大型应用程序常用的技术是会根据需要动态创建所需的控制器。这有助于减少应用程序的加载时间,且有助于在运行时通过不激活潜在的控制器已提供性能。这在之前的版本是不可能的,控制器一旦创建,就会在应用程序中保持活动状态,不会被销毁并释放资源。同样,这也没改变一个控制器可能包含任意数目的相关视图(包括没有视图)这一事实。
然而,ViewController会在组件生命周期的早期创建并将它的整个生命周期绑定在了视图。当视图被销毁的时候,ViewController同样也会销毁。这意味着,ViewController从此不用在没有视图或很多视图的时候被强迫去管理状态。
这种一对一的管理意味着引用跟踪被简化了,而且不再会轻易的因组件的销毁而出现泄漏。ViewController可在它生命周期内任何关键点内实现任何方法来处理事务。
beforeinit——该方法可被重写,它会在视图调用initComponent方法之前执行。该方法会在控制器创建之后立即被调用,而这会在组件的构造函数之内在调用initConfig方法期间发生。
init——在视图调用initComponent方法不久后会调用该方法。这通常会是视图初始化后,执行控制器初始化的时候,
initViewModel——在创建视图的ViewModel(如果存在)时会调用该方法。
destroy——清理任何资源(确保调用了callParent方法)。
我们相信ViewController将会大大简化你的MVC应用程序。他们还可以与ViewModels一起使用。因此,你可以结合这些方法以及他们的各自优势。我们很兴奋即将发布正式版以及看到这些在你的应用程序中所做的改进。
作者: Don Griffin
译者: 黄灯桥
关键字: , , ,
本站采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本站内容必须也遵循“署名-非商业用途-保持一致”的创作共用协议.Angularjs内置的过滤器(filter)为我们的数据信息格式化提供了比较强大的功能,比如:格式化时间,日期、格式化数字精度、语言本地化、格式化货币等等。但这些过滤器一般都是在VIEW中使用的,比如格式化时间/日期的VIEW视图代码:
&div ng-app&
&label&Select a date&/label&
&input type="date" id="date" ng-model="datevalue" /&
&p& {{ datevalue | date : 'fullDate'}} &/p&
那么问题来了,如果我需要在控制器(controller)的js代码中使用filter来格式化时间/日期,应该怎样处理呢? 直接上代码吧: 视图(view)模板代码:
&div ng-app="dateApp" ng-controller="dateController"&
&p& {{ result }} &/p&
控制器(controller)代码:
var app = angular.module('dateApp', []);
app.controller(
'dateController',
function ($scope, $filter) {
$scope.result = $filter('date')(new Date(), 'fullDate');
以上就是在控制器(controller.js)的js代码中使用过滤器($filter)格式化日期/时间的实现。
PS:如果有写错的地方,欢迎指出,谢谢。
阅读(...) 评论()}

我要回帖

更多关于 angularjs多个控制器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信