LOGO

组件API

编辑本文

该文档描述了组件的 API,在 San 主模块上暴露的 API 请参考文档 主模块API

初始化参数

data

解释

组件初始化数据。通常在组件反解的场景下使用。

类型: Object

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var MyComponent = san.defineComponent({});

var myComponent = new MyComponent({
el: document.getElementById('my-label'),
data: {
email: 'errorrik@gmail.com',
name: 'errorrik'
}
});

/* html:
<label id="my-label">
<span title="errorrik@gmail.com" prop-title="{{email}}">errorrik</span>
</label>

el

解释

组件根元素。传入此参数意味着不使用组件的 template 作为视图模板,组件视图由 San 自动反解。详情可参考组件反解文档。

类型: HTMLElement

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var MyComponent = san.defineComponent({});

var myComponent = new MyComponent({
el: document.getElementById('my-label'),
data: {
email: 'errorrik@gmail.com',
name: 'errorrik'
}
});

/* html:
<label id="my-label">
<span title="errorrik@gmail.com" prop-title="{{email}}">errorrik</span>
</label>
*/

生命周期钩子

生命周期代表组件的生存过程,在每个过程到达时将触发钩子函数。具体请参考生命周期文档。

compiled

解释

组件视图模板编译完成。组件上的 compiled 方法将会被调用。

inited

解释

组件实例初始化完成。组件上的 inited 方法将会被调用。

created

解释

组件元素创建完成。组件上的 created 方法将会被调用。

attached

解释

组件已被附加到页面中。组件上的 attached 方法将会被调用。

detached

解释

组件从页面中移除。组件上的 detached 方法将会被调用。

disposed

解释

组件卸载完成。组件上的 disposed 方法将会被调用。

updated

解释

组件由于数据变化,视图完成一次刷新。组件上的 updated 方法将会被调用。

定义组件成员

template

解释

组件的视图模板。详细描述请参考视图模板文档。

类型: string

用法

1
2
3
san.defineComponent({
template: '<span title="{{text}}">{{text}}</span>'
});

filters

解释

声明组件视图模板中可以使用哪些过滤器。详细描述请参考过滤器文档。

类型: Object

用法

1
2
3
4
5
6
7
8
9
san.defineComponent({
template: '<a>{{createTime | dateFormat('yyyy-MM-dd')}}</a>',

filters: {
dateFormat: function (value, format) {
return moment(value).format(format);
}
}
});

components

解释

声明组件中可以使用哪些类型的子组件。详细描述请参考components文档。

类型: Object

用法

1
2
3
4
5
6
var AddForm = san.defineComponent({
components: {
'ui-timepicker': TimePicker,
'ui-calendar': Calendar
}
});

computed

解释

声明组件中的计算数据。详细描述请参考计算数据文档。

类型: Object

用法

1
2
3
4
5
6
7
8
9
10
san.defineComponent({
template: '<a>{{name}}</a>',

// name 数据项由 firstName 和 lastName 计算得来
computed: {
name: function () {
return this.data.get('firstName') + ' ' + this.data.get('lastName');
}
}
});

messages

解释

声明处理子组件派发消息的方法。详细描述请参考消息文档。

类型: Object

用法

1
2
3
4
5
6
7
8
9
10
11
var Select = san.defineComponent({
template: '<ul><slot></slot></ul>',

messages: {
'UI:select-item-selected': function (arg) {
// arg.target 可以拿到派发消息的组件
var value = arg.value;
this.data.set('value', value);
}
}
});

initData

解释

返回组件实例的初始数据。详细描述请参考初始数据文档。

类型: function():Object

用法

1
2
3
4
5
6
7
8
9
var MyApp = san.defineComponent({
template: '<ul><li s-for="item in list">{{item}}</li></ul>',

initData: function () {
return {
list: ['san', 'er', 'esui', 'etpl', 'esl']
};
}
});

trimWhitespace

定义组件模板解析时对空白字符的 trim 模式。

  • 默认为 none,不做任何事情
  • blank 时将清除空白文本节点
  • all 时将清除所有文本节点的前后空白字符

版本:>= 3.2.5

类型: string

用法

1
2
3
4
5
6
var MyApp = san.defineComponent({
trimWhitespace: 'blank'

// ,
// ......
});

组件方法

fire

描述: fire({string}eventName, {*}eventArgument)

解释

派发一个自定义事件。San 为组件提供了自定义事件功能,组件开发者可以通过该方法派发事件。事件可以在视图模板中通过 on- 的方式绑定监听,也可以通过组件实例的 on 方法监听。可参考Event文档。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var Label = san.defineComponent({
template: '<template class="ui-label"><a on-click="clicker" title="{{text}}">{{text}}</a></template>',

clicker: function () {
this.fire('customclick', this.data.get('text') + ' clicked');
}
});

var MyComponent = san.defineComponent({
initData: function () {
return {name: 'San'};
},

components: {
'ui-label': Label
},

template: '<div><ui-label text="{{name}}" on-customclick="labelClicker($event)"></ui-label></div>',

labelClicker: function (doneMsg) {
alert(doneMsg);
}
});

on

描述: on({string}eventName, {Function}eventListener)

解释

添加自定义事件监听器。 on 一般仅用在使用 JavaScript 动态创建的组件中,通过视图模板创建的子组件应通过 on- 的方式绑定监听。可参考动态子组件文档

un

描述: un({string}eventName, {Function=}eventListener)

解释

移除事件监听器。 当 eventListener 参数为空时,移除所有 eventName 事件的监听器。

dispatch

描述: dispatch({string}name, {*}value)

解释

派发一个消息。消息将沿着组件树向上传递,直到遇到第一个处理该消息的组件。上层组件通过 messages 声明组件要处理的消息。消息主要用于组件与非 owner 的上层组件进行通信。可参考消息文档。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
var SelectItem = san.defineComponent({
template:
'<li on-click="select" class="{{value === selectValue ? \'selected\' : \'\'">'
+ '<slot></slot>'
+ '</li>',

// 子组件在各种时机派发消息
select: function () {
var value = this.data.get('value');
this.dispatch('UI:select-item-selected', value);
},

attached: function () {
this.dispatch('UI:select-item-attached');
},

detached: function () {
this.dispatch('UI:select-item-detached');
}
});

var Select = san.defineComponent({
template: '<ul><slot></slot></ul>',

// 上层组件处理自己想要的消息
messages: {
'UI:select-item-selected': function (arg) {
var value = arg.value;
this.data.set('value', value);

// 原则上上层组件允许更改下层组件的数据,因为更新流是至上而下的
var len = this.items.length;
while (len--) {
this.items[len].data.set('selectValue', value);
}
},

'UI:select-item-attached': function (arg) {
this.items.push(arg.target);
arg.target.data.set('selectValue', this.data.get('value'));
},

'UI:select-item-detached': function (arg) {
var len = this.items.length;
while (len--) {
if (this.items[len] === arg.target) {
this.items.splice(len, 1);
}
}
}
},

inited: function () {
this.items = [];
}
});

var MyComponent = san.defineComponent({
components: {
'ui-select': Select,
'ui-selectitem': SelectItem
},

template: ''
+ '<div>'
+ ' <ui-select value="{=value=}">'
+ ' <ui-selectitem value="1">one</ui-selectitem>'
+ ' <ui-selectitem value="2">two</ui-selectitem>'
+ ' <ui-selectitem value="3">three</ui-selectitem>'
+ ' </ui-select>'
+ '</div>'
});

watch

描述: watch({string}dataName, {function({*}value)}listener)

解释

监听组件的数据变化。通常我们使用绑定,在子组件数据变化时自动更新父组件的对应数据。 watch 一般仅用在使用 JavaScript 动态创建的组件中。可参考动态子组件文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
san.defineComponent({
// ...

initLayer: function () {
if (!this.monthView) {
var monthView = new MonthView();
this.monthView = monthView;

this.monthView.watch('value', (function (value) {
this.data.set('value', value);
}).bind(this));

this.watch('value', function (value) {
monthView.data.set('value', value);
});

this.monthView.attach(document.body);
}
}
});

ref

描述: ref({string}name)

解释

获取定义了 s-ref 的子组件。详细请参考组件层级文档。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var AddForm = san.defineComponent({
// template

components: {
'ui-timepicker': require('../ui/TimePicker'),
'ui-calendar': require('../ui/Calendar')
},

submit: function () {
this.ref('endDate')
this.ref('endHour')
}
});

/* template:
<div class="form">
<div>预期完成时间:
<ui-calendar bindx-value="endTimeDate" s-ref="endDate"></ui-calendar>
<ui-timepicker bindx-value="endTimeHour" s-ref="endHour"></ui-timepicker>
</div>

<div class="form-op">
<button type="button" on-click="submit">ok</button>
</div>
</div>
*/

slot

版本:>= 3.3.0

描述: {Array} slot({string=}name)

解释

获取组件插槽的节点信息。返回值是一个数组,数组中的项是节点对象。通常只有一项,当 slot 声明中应用了 if 或 for 时可能为 0 项或多项。节点对象包含 isScoped 、 isInserted 和 children。

插槽详细用法请参考 slot 文档。

注意:不要对返回的 slot 对象进行任何修改。如果希望操作视图变更,请操作数据。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var Panel = san.defineComponent({
template: '<div><slot s-if="!hidden"/></div>',
});

var MyComponent = san.defineComponent({
components: {
'x-panel': Panel
},

template: ''
+ '<div>'
+ '<x-panel hidden="{{folderHidden}}" s-ref="panel"><p>{{desc}}</p></x-panel>'
+ '</div>',

attached: function () {
// 1
this.ref('panel').slot().length

var contentSlot = this.ref('panel').slot()[0];

// truthy
contentSlot.isInserted

// falsy
contentSlot.isScoped
}
});


var myComponent = new MyComponent({
data: {
desc: 'MVVM component framework',
}
});

nextTick

解释

San 的视图更新是异步的。组件数据变更后,将在下一个时钟周期更新视图。如果你修改了某些数据,想要在 DOM 更新后做某些事情,则需要使用 nextTick 方法。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Component = san.defineComponent({
template: `
<div>
<div s-ref="name">{{name}}</div>
<button on-click="clicker">change name</button>
</div>
`,

initData() {
return {name: 'erik'};
},

clicker() {
this.data.set('name', 'leeight');
console.log(this.ref('name').innerHTML); // erik
this.nextTick(() => {
console.log(this.ref('name').innerHTML); // leeight
});
}
});