Skip to content

Nesting

TANG edited this page Dec 14, 2016 · 9 revisions

组件的嵌套(子组件的创建方式)

组件的嵌套对解决复杂的交互有很大的用处,sugar 支持命令式声明式两种组件嵌套方式。

命令式嵌套

组件的命令式嵌套实际上是调用组件 API 的 create 方法去实现子组件的嵌套/创建

var AnOtherComponent = sugar.Component.extend({/**/});

var MyComponent = sugar.Component.extend({
	init: function (config) {
		this.Super('init', config);
	},
	afterRender: function () {
		// 用 create 方法创建子组件
		this.create('sub', AnOtherComponent, {
			target: this.el // 子组件直接创建到当前组件容器内
		});

		// 用 getChild 获取子组件实例
		var sub = this.getChild('sub');
	}
});

// 添加到页面中:
sugar.core.create('mycomponent', MyComponent, {
	target: document.body
});

组件的命令式嵌套只能在组件渲染完毕(afterRender)之后使用,而且只能手动的去 create 子组件,这种方式只适用于嵌套组件数目很少的情况,大多数情况都推荐使用组件的声明式嵌套。

声明式嵌套

为了解决组件命令式嵌套的不足,视图组件还支持声明式嵌套(组件自定义标签):

var AnOtherComponent = sugar.Component.extend({
	init: function (config) {
		this.Super('init', config, {
			view: 'I am sub-component'
		});
	}
});

var MyComponent = sugar.Component.extend({
	init: function (config) {
		this.Super('init', config, {
			class: 'mycomp',
			view: `
				<h1>title</h1>
				<SubComponentOne></SubComponentOne>
				<SubComponentTwo></SubComponentTwo>
			`,
			// 子组件注册对象
			childs: {
				SubComponentOne: AnOtherComponent,
				// 也可用数组的形式添加子组件和它的配置参数
				SubComponentTwo: [AnOtherComponent, { class: 'subcomp' }]
			}
		});
	},
	afterRender: function () {
		var sub = this.getChild('SubComponentOne');
	}
});

sugar.core.create('mycomponent', MyComponent, {
	target: document.body
});

结果:

...
<body>
	<div class="mycomp">
		<h1>title</h1>
		<div>I am sub-component</div>
		<div class="subcomp">I am sub-component</div>
	</div>
</body>
...

组件声明式嵌套需要在组件内部布局用自定义标签 <SubName></SubName> 来表示,然后在配置参数 childs 中定义嵌套组件的信息(组件类和配置参数等)标签的位置就是嵌套组件的位置,标签的名称就是嵌套组件生成实例的名称。

声明式嵌套的组件将会在外部组件的渲染过程中同步创建,所以在所有嵌套的组件创建完成之后才会调用 afterRender 方法。

结合 v-for 的动态子组件列表创建

可以结合 MVVM 的 v-for 指令实现动态子组件的创建:

<body>
	<div id="app">
		<ul>
			<li v-for="sub in subs" v-hook:after="createSub" v-hook:before="removeSub"></li>
		</ul>
	</div>
</body>
var SubComponent = sugar.Component.extend({
	init: function (config) {/**/},
	// 返回子组件的数据
	getData: function () {
		return '子组件数据';
	}
});

var App = Sugar.Component.extend({
	init: function (config) {
		this.subids = [];
		this.Super('init', config, {
			target: '#app',
			model: {
				subs: [1,1,1]
			},
			hooks: {
				createSub: this.createSub,
				removeSub: this.removeSub
			}
		});
	},
	createSub: function (el, index, guid) {
		this.subids.push(guid);
		this.create(guid, SubComponent, {
			target: el
		});
	},
	removeSub: function (el, index, guid) {
		var sub = this.getChild(guid);
		if (sub) {
			sub.destroy();
			this.subids.$remove(guid);
		}
	},
	// 获取所有子组件的数据
	getAllData: function () {
		var childData = [];
		Sugar.util.each(this.subids, function (subid) {
			var sub = this.getChild(subid);
			if (sub) {
				childData.push(sub.getData());
			}
		}, this);
		return childData;
	}
});

项目的 打星评分 demo 也用了该方法来实现动态子组件列表的创建。


上一篇:组件的继承

下一篇:组件间的消息通信