实例组件
定义组件就是定义类,你可以手动调用new
实例化该类。Intact实例章节中,我们提到了怎么实例化,并且渲染它。但它是作为根组件挂载到页面中的。其实我们也可以将实例当做普通数据,就像插值一样在模板中直接渲染。这就是Intact支持的实例组件。
实例组件提供了直接操作组件的能力,你可以设置和获取组件渲染的各个细节。
var Component = Intact.extend({
template: '<div>{self.get("data")}</div>'
});
Intact.extend({
template: '<div>{self.get("view")}</div>',
defaults: function() {
return {
// 直接实例化组件
view: new Component({data: 'hello'})
}
}
});
另一个常见的例子是SPA应用中,使用前端路由切换页面。我们可能需要等到异步组件数据加载完毕才开始切换页面,并且在数据加载的过程中,需要展示loading动画。我们可以如下这么做:
var PageA = Intact.extend({
template: '<div>PageA, router: {self.get("router")}</div>',
_init: function() {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 1000);
});
}
});
var PageB = Intact.extend({
template: '<div>PageB, router: {self.get("router")}</div>',
_init: function() {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 1000);
});
}
});
上述两个组件都模拟1s来加载数据,下面我们定义一个根组件来管理它们。
<div>
{self.get('view')}
<div v-if={self.get('loading')}>Loading...</div>
<button ev-click={self.toggle}>加载组件</button>
</div>
// 模拟hash路由
var router = {
'/a': PageA,
'/b': PageB
};
var hash;
Intact.extend({
template: template,
toggle: function() {
this.set('loading', true);
hash = hash === '/a' ? '/b' : '/a';
var Page = router[hash];
// 实例化组件
var page = new Page({router: hash});
this.set('view', page);
// 判断实例是否数据加载完成
if (page.inited) {
// 如果加载完成
this.set('loading', false);
} else {
// 否则等实例加载完成后才挂载
page.one('$inited', function() {
this.set('loading', false);
}.bind(this));
}
}
});
实例组件让你可以控制组件的实例化,这在前端路由中很实用。例如:/user/1
和/user/2
两个页面都对应同一个组件,只是参数不同,这样你可以为每个页面实例化一个组件传入不同的用户ID。如果不采用实例组件,你可能需要为每个组件指定一个唯一的key
,否则因为是同一个组件,两个页面不是替换关系,而是更新,这样上一个页面的数据就会带到下一页了。当然你也可以监听用户ID的变化,只是这样处理起来不如实例组件来的简单。