Dojo widget 系统 - dijit._WidgetBase类(1)

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;
}






你可能感兴趣的:(JavaScript,JavaScript,JavaScript,JavaScript,核心,dojo,dojo,widget,dijit)