当前位置: 首页 > news >正文

解读sencha touch移动框架的核心架构(一)

sencha的前身就是Extjs了,sencha 框架是世界上第一个基于HTML5的Mobile App框架

那么何谓框架,传统软件工程对于库和框架的区分主要着眼于对应用运行流程的控制权,框架提供架构,控制运行流程,让开发者在合适的地方书写针对具体问题的代码

sencha提倡的就是组件化编程,是面向对象的技术的一种近一步的发展延伸,类的概念仍然是组件技术中一个基础的概念,但是组件技术更核心的概念是接口。

sencha是重量级的架构了,一般来说很少会有公司用到内部的这种架构,因为太像java的Swing了

不过我在项目中用sencha组织的代码结构拿来主义本来不是我的风格,自己也改动了很多代码, 但是整体的设计还是参考的sencha了

有项目图为证:3万行以上的纯js代码架构哦~

AMD + sencha核心

AMD模块

sencha架构模块

AMD/CMD的实现只用了100行不到的代码,只是为简单的管理模块

在强类型语言中,继承机制是得到语言本身的支持的,就算代码开发者比较一般,也不会出太大的问题,但是js就不同了,要实现这一套机制就有一套很复杂的模拟

当然这里性能与维护扩展本来就是一个单选题 - -.

当然像backbone这种也是类似的提供纯架构方案

为什么我选择sencha作为参考架构呢?

高端大气上档次

关于Ext/sencha的好与坏这里就不多加讨论了,它的精华是需要你去慢慢体会的

 


按照最新sencha 2.3.1源码的区分

从Ext4.0开始,风格大变,提供一个完整的沙箱模式

就只针对core文件夹的内容,具体就是这么几个文件了,

Ext.js,Base.js,Class.js,ClassManager.js,Loader.js

这里是架构的核心文件,架构真心有点复杂,先看看历史的演变,老版本的架构

 


EXTJS组件化编程

组件化的简单定义:

组件化的基础是面向对象,在面向对象编程的基础上将一个或多个小部件封装到一起,成为一个模块,让其成为一个新的组件(适合我们需求的组件),每一个模块都应当具备单独运行的能力

image

通过继承来实现了对象的封装,ExtJS最底层的那个基类是Observable,它提供了最基础的事件机制,通过层层的封装与扩展,它的派生类中是越来越庞大,所提供的功能也越来越多,就比如Window这个组件,它继承自Panel并添加了默认的resizabel,closable,draggable等属性(Panel也可以加入类似的函数,但是需要编码实现)。而Panel又继承自Container,并加入了渲染Title和tbar等功能

 


先看老版本的实现继承的机制

Ext.extend( superclass, overrides )  在4.0后就作废了,统一换成了Ext.define的架构方式

先看3.4版本的,之后在过渡4.0,发现是一个多么大的跨越

复制代码
Ext.apply(Ext, {

        /**
         * This method deprecated. Use {@link Ext#define Ext.define} instead.
         * @method
         * @param {Function} superclass
         * @param {Object} overrides
         * @return {Function} The subclass constructor from the `overrides` parameter, or a generated one if not provided.
         * @deprecated 2.0.0 Please use {@link Ext#define Ext.define} instead
         */
        extend: function() {
            // inline overrides
            var objectConstructor = objectPrototype.constructor,
                inlineOverrides = function(o) {
                for (var m in o) {
                    if (!o.hasOwnProperty(m)) {
                        continue;
                    }
                    this[m] = o[m];
                }
            };

            return function(subclass, superclass, overrides) {
                // First we check if the user passed in just the superClass with overrides
                if (Ext.isObject(superclass)) {
                    overrides = superclass;
                    superclass = subclass;
                    subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
                        superclass.apply(this, arguments);
                    };
                }

                //<debug>
                if (!superclass) {
                    Ext.Error.raise({
                        sourceClass: 'Ext',
                        sourceMethod: 'extend',
                        msg: 'Attempting to extend from a class which has not been loaded on the page.'
                    });
                }
                //</debug>

                // We create a new temporary class
                var F = function() {},
                    subclassProto, superclassProto = superclass.prototype;

                F.prototype = superclassProto;
                subclassProto = subclass.prototype = new F();
                subclassProto.constructor = subclass;
                subclass.superclass = superclassProto;

                if (superclassProto.constructor === objectConstructor) {
                    superclassProto.constructor = superclass;
                }

                subclass.override = function(overrides) {
                    Ext.override(subclass, overrides);
                };

                subclassProto.override = inlineOverrides;
                subclassProto.proto = subclassProto;

                subclass.override(overrides);
                subclass.extend = function(o) {
                    return Ext.extend(subclass, o);
                };

                return subclass;
            };
        }(),

        /**
         * Proxy to {@link Ext.Base#override}. Please refer {@link Ext.Base#override} for further details.
         *
         * @param {Object} cls The class to override
         * @param {Object} overrides The properties to add to `origClass`. This should be specified as an object literal
         * containing one or more properties.
         * @method override
         * @deprecated 2.0.0 Please use {@link Ext#define Ext.define} instead.
         */
        override: function(cls, overrides) {
            if (cls.$isClass) {
                return cls.override(overrides);
            }
            else {
                Ext.apply(cls.prototype, overrides);
            }
        }
    });
复制代码

在4.0以前的架构还是相对比较简单的,只是用了一个关键的继承,不像4.0以后那就是一套完整的沙箱架构

针对JS的继承机制,那本红本书高3已经把细节讲的很透彻了

当然也有漏掉的,比如创建一个空函数的作用

var F = function() {},
     F.prototype = superclassProto;
     subclassProto = subclass.prototype = new F();

backbone的继承机制基本大同小异

 


实现详解

一般继承的手段无非就是两种,原型继承与对象冒充

⒈原型继承就是利用了原型的查找合函数的作用域,好处就是内存处只有一份,坏处就是原型是共享的,如果有引用类型所有的实例都可以被修改

⒉对象冒充就是拷贝属性了,把所有的实例属性与方法都拷贝一次,坏处自然就是每一份拷贝都是占独立的一份空间了

原型继承自然就是引用原型链了,这个prototype没什么好说的,但是不能继承静态属性,因为这个不在原型链上

对象冒充,就是通过call,apply处理的,因为JS有运行作用域的,要注意了prototype上的的属性是不会被处理的

现在看看Ext的完美解决方案

看下面例子,实现一个最基本的继承

复制代码
var a = function(id){
    this.name = id;
}

a.prototype = {
    sayA : function(){
        alert(this.name)
    }
};

var b = Ext.extend(a, {
    constructor:function(name){
        this.name = name;
    },
    sayB : function(){
        this.constructor.superclass.constructor(111)
    }
});

c =  new b('Aaron')
复制代码

ext需要解决的问题

1 构造器问题:类b没有构造器,直接是通过Ext.extend生成的,所以内部可定需要类似工厂方法,生成一个类的包装器

2 父类调用:原型只能继承原型链上的属性与方法,如果要调用父类构造器,如何处理?所以ext需要留一个接口出来可以调用父类

3 静态方法处理

4 实现继承后,构造器引用被修改

 

本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3578495.html,如需转载请自行联系原作者

相关文章:

  • DataView(2):RowState
  • Spark学习笔记之相关记录
  • Js实现Repeater全选/反选 功能 终极解决方案
  • MySQL主从复制读写分离及奇怪的问题
  • SQL server 2005中新增函数及操作(ZT)
  • 智能分单算法
  • NHibernate.Search 基于Lucene.NET的全文索引
  • mail退信!
  • 在Spring中发现java.lang.ClassCastException: $Proxy1问题解析
  • (转)setTimeout 和 setInterval 的区别
  • Bing正在让Image Graphic变得更加实用、吸引人
  • 持久数据层框架设计(二)
  • 《编译原理实践与指导教程》——第1章 词法分析与语法分析
  • gtest中如何跳出当前测试案例
  • linux-image-2.6.27-7-generic_2.6.27-7.16_i386.deb 无法安装
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • git 常用命令
  • Git初体验
  • Iterator 和 for...of 循环
  • JavaScript 基本功--面试宝典
  • Javascript 原型链
  • Javascript弹出层-初探
  • Javascript设计模式学习之Observer(观察者)模式
  • leetcode46 Permutation 排列组合
  • Tornado学习笔记(1)
  • unity如何实现一个固定宽度的orthagraphic相机
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 从0到1:PostCSS 插件开发最佳实践
  • 京东美团研发面经
  • 使用SAX解析XML
  • ​MySQL主从复制一致性检测
  • #include<初见C语言之指针(5)>
  • #pragma预处理命令
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (13):Silverlight 2 数据与通信之WebRequest
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • *2 echo、printf、mkdir命令的应用
  • . NET自动找可写目录
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .NET Core 版本不支持的问题
  • [ARC066F]Contest with Drinks Hard
  • [bzoj1006]: [HNOI2008]神奇的国度(最大势算法)
  • [BZOJ2850]巧克力王国
  • [CareerCup] 17.8 Contiguous Sequence with Largest Sum 连续子序列之和最大
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • [FTP]pureftp部署和优化
  • [IE技巧] IE 中打开Office文件的设置