Skip to content

YMPlayer 4: "make()" method

吟夢ちゃん edited this page May 28, 2017 · 1 revision

"make()" method (Chinese simplified)

之所以把 make() 方法单独拿出来讲,是因为这是 YMPlayer 4 中封装的最重要的方法之一,也就是一个很重要的“轮子”。

What is make() ?

make() 方法用于创建一个 DOM 节点,它接受描述该节点的参数,在执行后将返回根据您的描述所构建的 DOM 节点。

make (element, attributes, inner, events)

如果你熟悉 AngularJS 或是 React ,你将不会对这样的构建方式陌生。

Usage

之前谈到,在 new YMPlayer() 执行后,YMPlayer 类的实例化对象会被注册到 window.YMPlayer 上。所以我们可以直接通过 YMPlayer.make() 调用 make() 方法。

在使用之前,请看一下对此方法各个参数的简介:

attribute type required description
element String true 指定所新建元素的类型,如 div, p , ymplayer
extra mixed false 为所新建的元素注入属性
inner mixed false 设置新建元素的内容 (innerHTML)
events Object false 为新建的元素绑定事件

element 接受字符型参数,用于指定新建元素的 TagName。考虑下面的代码:

let node = this.make('div');

// 等价于 
let node = document.createElement('div');

extra 接受字符型或对象型参数,用于指定新建元素的各种属性值。看下面的示例:

let node = this.make('div', {
	className: 'ymplayer',		// class 在 ES6 是关键字,所以使用 className 代替
	id: 'app'
});

// 可以简写为

let node = this.make('div', 'class=ymplayer|id=app');		
/* 不同的参数间使用 | 分隔,用 = 赋值,无需将 class 改写为 className */

以上代码将会产生这样的元素:

<div class="ymplayer" id="app">
</div>

注意,由于 make() 方法默认返回的是 HTML 元素的示例 (instance of HTMLElement),如果要让其返回字符串,需要在 extra 中指定 stringify 属性为 true。


inner 接受字符型参数、HTML 对象型参数或数组,数组内容必须是 HTML 元素对象。当你需要向其中添加多个节点时,便可以使用数组。

let node = this.make('div', null, 'foo');		// <div>foo</div>

let node2 = this.make('div', null, this.make('p', null, 'bar'));	// <div> <p>bar</p> </div>

let nodes = [this.make('p', null, 'foo'), this.make('span', null, 'bar')];
let node3 = this.make('div', null, nodes);	//<div> <p>foo</p> <span>bar</span> </div>

events 接受对象型参数,为新元素绑定事件。以下以为元素绑定 mousedownmouseup 事件为例:

this.make('div', null, 'Hey!', {
	mousedown: function () {
		/* 由于该方法将通过 addEventListener 注册,所以这里的 this 是新元素的指针 */
		this.innerHTML = 'foo';
	},

	/* 或者使用箭头函数,但要小心 this 作用域的变化 */
	mouseup: (e) => {
		let src = e.srcElement || e.target;		// 获取事件目标
		src.innerHTML = 'bar';
	}
});

像上面这样做,最终的效果是当你将这个元素渲染到 DOM 上后,单击它,它的内容将被改变为 foo,松开鼠标后将变为 bar.

Source Code

以下是 make() 方法的原型,供参考:

/**
 * DOM Node creator
 *
 * @param  {string} element
 * @param  {mixed} extra
 * @param  {mixed} inner
 * @param  {Object} events
 * @return {Object}
 */
make (element, extra, inner, events) {
	var node = document.createElement(element);

	/* Inject attributes */
	if (extra && extra != null) {
		switch(typeof extra)
		{
			case 'string':
				var attrs = extra.split('|');
				attrs.forEach(function(index) {
					var detail = index.split('=');
					node.setAttribute(detail[0], detail[1]);
				});
				break;

			case 'object':
				for (var i in extra)
				{
					if (i == 'className')
						var attrName = 'class';
					else
						var attrName = i;
					node.setAttribute(attrName, extra[i]);
				}
				break;
		} // switch
	} // if

	/* Dangerously set inner content */
	if (inner && inner != null) {
		switch (typeof inner)
		{
			case 'object':
				inner instanceof HTMLElement ? node.appendChild(inner) :
				inner instanceof Array ? (inner.forEach(function (index) {
					node.appendChild(index);
				})) : '';
				break;

			case 'string':
				node.innerHTML = inner;
				break;
		}
	}

	/* Event listener */
	if (events && events != null) {
		for (var eventName in events)
		{
			node.addEventListener(eventName, events[eventName]);
		}
	}

	/* stringify for setting innerHTML */
	if (extra && extra.stringify) {
		var virtualDOM = document.createElement('div');
		virtualDOM.appendChild(node);
		return virtualDOM.innerHTML;
	}

	return node;
}