Dojo Widget系统(转)
Dojo 里所有的小部件(Widget)都会直接或间接的继承 dijit._Widget / dijit._WidgetBase
dijit._Widget 是 dojo 1.6 和 1.6之前的版本的基类, 在 dojo 1.7 之后的版本, 官方建议直接继承 dijit._WidgetBase 类(继承 dijit._Widget 也可以, dijit._Widget 继承了 dijit._WidgetBase).
Dojo 里丰富多彩的 Widgets 都是以这个类为基础, 那么这个类到底内藏了什么玄机呢? ...
查看 dijit._WidgetBase (dojo 1.6) 的类定义:
{
    // widget 的 id, 唯一的, 如果用户指定了 id 并且是不重复的用
    //     使用, 否则将忽略, 系统生成一个.
    id: "",
    // widget 的语言, 很少用
    lang: "",
    // 方向, "ltr" or "rtl"
    dir: "",
    // 最终生成的 widget 根结点上的 css class name
    "class": "",
    // 最终生成的 widget 根结点上的 inline css style,
    //    类型可以是: 一个字符串, 或 Object {width: '80px'}
    style: "",
    // 作用1: 相当于标准的 HTML title 属性, mouse hover 的时候有个tooltip
    // 作用2: 当这个 widget 是 TabContainer, AccordionContainer 的子 widget
    //        的时候, 就对应特定 widget 的 title, 比如 tab name.
    title: "",
    // 和上面的 title 属性合作, 当 title 被当成 tab name, ... 时, tooltip
    //    属性指的就是标准的 HTML title 属性
    tooltip: "",
    // widget 根节点上的 class, 用来创建指示 widget 状态(State)的 css classes
    baseClass: "",
    // 引用原始的 DOM 节点(widget 要被创建在这个节点上)
    srcNodeRef: null,
    // 引用 widget 在页面上生成后的 DOM Node
    domNode: null,
    // 当 widget(比如 ContentPane) 接受 innerHTML / 子widget 的时候, 一定要定义这个属性,
    //    它指示 innerHTML / 子 widget 插入到哪个节点里
    containerNode: null,
    // 把 widget 的属性和其 DOM 节点绑定
    attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""},
    // Path to a 1x1 image, 占位, widget icon图片会被真正 css background image 取代
    //    方便运用 css sprit 技术
    _blankGif: (dojo.config.blankGif ||
        dojo.moduleUrl("dojo", "resources/blank.gif")).toString()
}
============================
Widget 的生命周期:
constructor
postscript
|---create
    |---postMixInProperties ( 刚刚读入了用户定义的属性 )
    |---buildRendering  ( 创建 widget.domNode )
    |---postCreate ( 此函数被触发时, widget.domNode已经被创建好了, 但是**并不一定**已经被连接到页面的 DOM 结构中
                              所以, 此函数内最好不要执行 place 定位, 以及计算dom node 占页面尺寸等相关操作)
startup
** 很多讲 Widget 系统的文章都斩钉截铁地说, postCreate() 是在 dom fragment创建好了, 但是还没有连到页面DOM树中去的时候触发, 看了源码, 又做了测试后发现这是不对的. 此时有可能已经连到DOM树中, 也可能没有.**
============================
Widget.postscripte
postscript: function(params, srcNodeRef) {
    this.create(params, srcNodeRef);
}
开始. 参数 params 是 Object 初始化 widget 的属性, srcNodeRef 为 Dom node / String
这个函数只是调用了 create 函数, 由 create 完成具体的 初始化 操作.
=============================
Widget.create
function create(/*Object?*/params, /*DomNode|String?*/srcNodeRef) {
    // 保存在页面上的, 之后要被转换为 Widget 的节点
    this.srcNodeRef = dojo.byId(srcNodeRef);
    // 保存所有 dojo.connect() 返回的句柄, 用于垃圾回收, 阻止内存溢出
    this._connects = [];
    // 保存所有 dojo.subscribe() 返回的句柄, 用于垃圾回收, 阻止内存溢出
    this._subscribes = [];
    // mix in our passed parameters
    if(this.srcNodeRef && ( typeof this.srcNodeRef.id == "string")) {
        // 页面上的 Dom node 的 id, 做为 widget 的 id
        this.id = this.srcNodeRef.id;
    }
    if(params) {
        // 添加用户自定义的属性和方法
        this.params = params;
        dojo._mixin(this, params);
    }
    // 当 mixin 完成后, 调用 postMixInProperties()
    this.postMixInProperties();
    // 如果, 此时仍没有 id 属性, 系统自动生成一个 id
    if(!this.id) {
        // Example: dijit_Tooltip_1
        this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g, "_"));
    }
    // 将当前 widget 加入到 dijit.registry 列表中
    dijit.registry.add(this);
    // 确定有了 id 后, 调用 buildRendering()
    this.buildRendering();
    if(this.domNode) {
        // 将 attributeMap 中的所有属性 copy 到新建 widget 的 Dom node 上
        this._applyAttributes();
        // 用真正的 widget's dom node 替换页面中占位的 dom node
        var source = this.srcNodeRef;
        if(source && source.parentNode && this.domNode !== source) {
            source.parentNode.replaceChild(this.domNode, source);
        }
    }
    if(this.domNode) {
        // 为 dom node 添加 widgetId 属性
        this.domNode.setAttribute("widgetId", this.id);
    }
    // ** 很重要的方法 postCreate()
    this.postCreate();
    // 如果 srcNodeRef 已经被真正的 widget dom node 替换了, 就删除它, 方便
    // GC回收资源
    if(this.srcNodeRef && !this.srcNodeRef.parentNode) {
        delete this.srcNodeRef;
    }
    // 设置标记
    this._created = true;
}
=============================
Widget.postMixInproperties
postMixInProperties: function() {
    // 此时已经读入了用户初始化 widget 的属性,
    // 但是, widget template 还没有始初化, 在这函数里可以设置
    // template 里的相应属性
}
=============================
Widget.buildRendering
buildRendering: function() {
    // 设置 widget 的 domNode 属性, 添加相应 css classes
    if(!this.domNode) {
        this.domNode = this.srcNodeRef || dojo.create('div');
    }
    // 如果页面 UI 为 rtl style, 则在所有 css class 加 Rtl 后缀
    if(this.baseClass) {
        var classes = this.baseClass.split(" ");
        if(!this.isLeftToRight()) {
            classes = classes.concat(dojo.map(classes, function(name) {
                return name + "Rtl";
            }));
        }
        dojo.addClass(this.domNode, classes);
    }
}
=============================
widget.postCreate
此时, 代表新建的 widget 的 dom node 已经完全创建好了, 但是并不一定已经被连入了主页面的 dom tree.
我们可以在这个函数里面做最多的自定义操作, 实际上, 我们自己写 widget 的时候, 大多数的操作也在这个函数里面进行
=============================
widget.startup
当这个函数触发的时候, widget's dom node 已经连到了页面上的DOM中, 相关联的 widgets 也完成了 create() 周期.
当自定义的 widget 有子 widgets 的时候, 这个方法就非常有用.
对于 layout widget 这个方法也很有用.
startup: function() {
    this._started = true;
}
widget destroy 的通用函数是 widget.destroyRecursive()
destroyRecursive: function(/*Boolean?*/ preserveDom) {
    this._beingDestroyed = true;
    this.destroyDescendants(preserveDom);
    this.destroy(preserveDom);
}
this.destroyDescendants(preserveDom)
作用: 如果这个 widget 有子 widget, 会遍历所有 子widget, 并在其上面递归调用 destroyRecursive() .
this.destroy(preserveDom)
这个函数主要进行了清理工作, 内部处理过程按顺序如下 :
1) 调用 uninitialize(). 这个函数在基类中是空函数, 专门留组用户去覆盖, 做一些自定义的析构操作
2) 清除所有 dojo.connect + dojo.subscribe 的句柄
3) 销毁做为模版的一部分而创建的 widget
4) 调用 dwstroyRendering(preserveDom), 这个函数会根据参数 preserveDom 为 true / false 去选择, 只是删除 domNode 上的 widgetId 属性, 或是直接把 domNode destroy掉
来自:http://blog.csdn.net/zsp_1111/article/details/8440781
Dojo Widget系统(转)的更多相关文章
- Dojo Widget中的全局变量
		转自http://blog.163.com/mqsy_yj/blog/static/2940499220121014115338929/ 前期设计了一个清除widget的功能,虽然可以从html文件中 ... 
- 认识dojo
		Dojo是一个强大的面向对象JavaScript框架.主要由三大模块组成:Core.Dijit.DojoX.Core提供Ajax,events,packaging,CSS-based querying ... 
- Dojo Data Store——统一数据访问接口
		原文地址:http://www.infoq.com/cn/articles/wq-dojo-data-store 无论在传统的桌面应用还是在主流的互联网应用中,数据始终占据着软件应用中的核心地位.当下 ... 
- Dojo API中文 Dojo内容模块概览,初学者
		官网:http://dojotoolkit.org/reference-guide/1.10/dojo/index.html#dojo-dojo的翻译 dojo 内容: dojo dojo/dojo ... 
- 基于 Dojo toolkit 实现 web2.0 的 MVC 模式
		前言 MVC 模式是设计模式中的经典模式,它可以有效的分离数据层,展示层,和业务逻辑层.Web2.0 技术由于其良好的用户体验被广泛应用于 WEB 应用的展示层.但是在传统的 web 开发中,展示层的 ... 
- 使用 Dojo 掌握面向对象开发
		原文出处:Joe Lennon 从头开始学习 Dojo,第 2 部分 使用 Dojo 掌握面向对象开发 什么是面向对象开发? 面向对象编程(Object-Oriented Programming,OO ... 
- 使用dojo.connect()添加事件的注意事项
		使用dojo.connect()添加事件处理器是很方便的,不用再考虑跨浏览器的问题了.但要想正确地使用这个方法,仍然要注意几个问题: 1.用dojo.byId()获取的是dom元素,而用 ... 
- dojo框架笔记
		一.模块定义 1.定义只含值对,没有任何依赖的模块(moudle1.js) define({ color: "black", size: "unisize" } ... 
- javascript进阶——测试和打包分发
		建立一个面向对象的好的代码基础后,为了达到代码重用的目的,通过调试使用适当的测试用例进行测试尤为必要,之后就是打包分发的主题. 一.调试与测试 1.调试 Firebug:包含了错误控制台.调试器.DO ... 
随机推荐
- SQL server 数据库日志文件过大清空日志文件
			SQL2008:'在SQL2008中清除日志就必须在简单模式下进行,等清除动作完毕再调回到完全模式. USE [master] GO ALTER DATABASE DBName SET RECOVER ... 
- JAVA中REPLACE和REPLACEALL的区别(转)
			replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是: 1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(Char ... 
- iss 防火墙
			控制面板\系统和安全\Windows 防火墙\允许的程序 如下图 将万维网服务(HTTP)打勾即可访问你的网站. 转自:http://bbs.pcbeta.com/viewthread-604506- ... 
- C# ACM poj1004
			水题.. public static void acm1004(float[] a) { ; foreach (var item in a) { sum += item; } Console.Writ ... 
- C++ txt文档读取
			void readfile(string filepath){ ifstream myfile; if (!myfile) { cout << "打开文件出错!"; e ... 
- ajax查询数据返回结果不变
			在使用流水号的时候,Google浏览器没有问题,但是IE有缓存,如果ajax请求的参数没有变化,那么就会返回缓存里的数据 解决方法:ajax请求的时候传值的参数设置一个时间戳就OK了(没什么特别意义, ... 
- 网络编程之UDP协议
			UDP协议 UDP(User Datagram Protocol)也就是用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范. 提 ... 
- bat文件的妙用1-一键开启所有开发软件
			每天早上来的第一件事情,就是打开电脑,然后开一堆的软件 1.wamp 开发环境 2.钉钉 通讯工具 3.PHPstrom 开发工具 4.nodejs.bat Nodejs的扩展(node D:/w ... 
- CentOS上无法识别NTFS格式分区的解决方法
			插入U盘之后,按照下面的步骤: # fdisk -l /dev/sd* 通常这一步就能找到U盘,如果U盘有指示灯也会亮,表示被找到. # mount –t ntfs /dev/sdb1 /mnt/ ... 
- Java Web开发中的名词解释
			1.JVM Java虚拟机,class文件的运行时环境,就好比软件运行在操作系统一样,java要运行在JVM中才行,这也是Java之所以支持扩平台的基础. 2.Servlet/JSP 是满足一定接口需 ... 
