Extjs4 MVC程序Controller两次init错误原因

注意:使用的Ext版本为4.2.1

本文指出一些书本和很多网站给出的、可能会让您的MVC程序隐藏有Bug的代码。如果你使用搜索引擎搜到这篇文章,那么你肯定已经使用了firebug或者opera dragonfly调试你的代码,发现了你的MVC程序中创建一个新的Controller的时候,该Controller的init方法执行了两次,而且很有可能由于init方法中初始化了对应的View,这个View就也被创建了两次,如果View中有一些定时执行的代码,那么就最糟了。本人的程序就是这样,两个同类型View,一个覆盖在了另外一个之上而被隐藏了,同时两个View还定时更新,一个View一旦更新了,它就会覆盖另外一个。

有关Extjs MVC应用程序编程的帖子或者书本(本人使用黄灯桥的《Ext js权威指南》也有误)中对于创建一个新的controller使用代码分别举例如下:

从一个博客copy的,使用ExtJS 4.1:

for (i = 0; i < ln; i++) {
     controller = me.getController(controllers[i]);
     controller.init(me);
}

黄灯桥的《Ext js权威指南》P952 switchPage函数中最后一行代码,使用的也是ExtJS 4.1:

me.getController(Ext.String.captitalize("your controller name")).init();

 

首先说明以上代码Ext4.1中应该是正确的,但是在Ext4.2版本中是错误的,而且这个错误还挺隐蔽的。原因就是4.2中,me.getController()方法源码已经执行了对应Controller的init方法,完了后上面的代码又调用了一次init()方法,看4.2中的Ext.app.Controller类的源代码:

    /**
     * Returns instance of a {@link Ext.app.Controller Controller} with the given id.
     * When controller doesn't exist yet, it's created. Note that this method depends
     * on Application instance and will return undefined when Application is not
     * accessible. The only exception is when this Controller instance's id is requested;
     * in that case we always return the instance even if Application is no available.
     *
     * @param {String} id
     *
     * @return {Ext.app.Controller} controller instance or undefined.
     */
    getController: function(id) {
        var me = this,
            app = me.application;

        if (id === me.id) {
            return me;
        }

        return app && app.getController(id);
    },

Controller类的getController其实调用了Ext.app.Application.getController()方法,源代码如下:

    getController: function(name) {
        var me          = this,
            controllers = me.controllers,
            className, controller;

        controller = controllers.get(name);

        if (!controller) {
            className  = me.getModuleClassName(name, 'controller');

            controller = Ext.create(className, {
                application: me,
                id:          name
            });

            controllers.add(controller);

            if (me._initialized) {
                controller.doInit(me);
            }
        }

        return controller;
    },

if语句中,创建了controller并且执行了doInit方法,不再贴代码了,doInit执行了controller的init方法。

所以回头看代码:

me.getController(Ext.String.captitalize("your controller name")).init();

其实就是执行了两次controller的init方法,如果在controller的init方法中载入了View,那么就会产生两个View实例。

所以为了保险起见,正确的写法应该就是用getController方法就可以了,不要再加init():

me.getController(Ext.String.captitalize("your controller name"));

 

另外说明一下为什么在Extjs4.1中应该是正确的,上文中说到的博客和《Extjs权威指南》使用了Extjs4.1,其Ext.app.Controller.getController方法源码,比4.2来的简单:

    /**
     * Returns instance of a {@link Ext.app.Controller controller} with the given name.
     * When controller doesn't exist yet, it's created.
     * @param {String} name
     * @return {Ext.app.Controller} a controller instance.
     */
    getController: function(name) {
        return this.application.getController(name);
    },

和4.2一样,也是调用了Ext.app.Application.getConroller方法,上源码:

    getController: function(name) {
        var controller = this.controllers.get(name);

        if (!controller) {
            controller = Ext.create(this.getModuleClassName(name, 'controller'), {
                application: this,
                id: name
            });

            this.controllers.add(controller);
        }

        return controller;
    },

可以对比上文中4.2的代码,发现4.1中没有

controller.doInit(me);

这行代码。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值