理解Kissy框架的Base机制

理解Base API

Kissy的Base机制非常强大,官方文档对Base的解释并不全面,官方文档为Base API

extend()

官网extend()解释为从当前类上扩展出一个子类

callSuper()

调用父类的对应方法,如果没有,则返回undefined,直接看用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
KISSY.use('base', function(S, Base) {
var A = Base.extend({
m: function (value) {
return 'am:' + value;
},
m2: function (value) {
return 'am2:' + value;
}
});
var B = A.extend({
m: function(value) {
return 'bm:(' + this.callSuper(value) + ')';
},
m2: function(value) {
//获取B的父类A对应的方法,获取A的参数
return 'bm2(' + this.callSuper.apply(this, arguments) + ')';
}
});
var b = new B();
console.log(b.m(1)); //bm:(am:1)
console.log(b.m2(2)); //bm2:(am:2)
});

ATTRS

ATTRS是Base的配置项,提供了默认的三种属性。

1.提供默认值(value)
2.提供获取属性值时的函数封装(getter)
3.提供设定属性值时的函数封装(setter)

举个例子,关键部分代码如下:

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
Keystone.ATTRS = {
backgroundColor: {
// 默认值
value: '#F50',
// this.set('backgroundColor', '#ddd'); 的时候会调用的方法
setter: function(v) {
if (/^\#[0-9a-f]{6}$/i.test(v) || /^\#[0-9a-f]{3}/i.test(v)) {
return v;
}
else {
return '#F50';
}
},
// this.get('backgroundColor') 时会调用的方法
getter: function(v) {
if (v.length === 4) {
return '#' + v.substr(1).replace(/\w/ig, function(c) {
return c.toUpperCase() + c.toUpperCase();
})
}
else {
return v.toUpperCase();
}
}
}
};

Base的demo

来解析一下官网提供的一个kissy Base的demo。抽出骨架来看一下Base模块,为防止误会,这里把ATTRS里的validator()给删了,validator()是kissy中value特有的方法,ATTRS配置项中通常只允许有value,setter(),getter()三种配置项。

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
KISSY.use('base, node, event', function(S, Base, Node, Event) {
var $ = Node.all;
// 自定义类
// 继承 Base
var Person = Base.extend({
sayHi: function(name) {
alert("Hi, " + name + "! Nice to meet you!");
//触发自定义事件
this.fire('say');
},
tellName: function() {
alert("My name is " + this.get('name') + ".");
this.fire('say');
},
tellAge: function() {
alert("I'm " + this.get('age') + " years old.");
this.fire('say');
},
introduce: function(extra) {
alert("Hello everyone, my name is " + this.get('name') + ", and I'm " + this.get('age') + " years old." + extra);
this.fire('say');
}
},{
ATTRS: {
name: {
//设置默认值
value: ""
},
age: {
value: 1,
},
gender: {
value: Gender.MALE,
/*
指定setter和getter方法的操作
*/
setter: function(value) {
if ( S.isString(value) ) {
return Gender[value.toUpperCase()];
}
return value;
},
getter: function(value) {
return S.keys(Gender)[value];
},
}
}
});
window.person = new Person({
name: "Andy",
age: 18,
gender: "female"
});
/*
继承Person
*/
var Student = Person.extend({
introduce: function() {
//调用父类方法
this.callSuper("I'm a student of " + this.get('school') + ".My hometown is " + this.get('from') + ".");
},
addScore: function(subject, score) {
//error异常收集
//设置子属性
this.set('score.' + subject, score, {
error: function(e) {
console.log(e);
}
});
},
/*
bind属性变化的方法
*/
_onSetScore: function(value, ev) {
if (!S.isEmptyObject(value)) {
alert('Score change');
alert(this.get('score'));
}
}
}, {
ATTRS: {
school: {
value: ""
},
from: {
value: ""
},
score: {
}
}
});
var Teacher = Person.extend({
introduce: function() {
this.callSuper("I'm a " + this.get('level') + "teacher, and I teach " + this.get('teach') + ".");
},
upLevel: function() {
this.set('level', this.get('level') + 1, {
error: function(e) {
alert(e);
}
});
},
downLevel: function() {
this.set('level', this.get('level') - 1, {
error: function(e) {
alert(e);
}
});
}
}, {
ATTRS: {
teach: {
value: ""
},
level: {
value: Level.PRIMARY,
setter: function(value) {
if ( S.isString(value) ) {
return Level[value.toUpperCase()];
}
return value;
}
}
}
});

tips:kissy.add()与kissy.use()

kissy.add()与kissy.use()的区别是,kissy.add()只加载模块,kissy.use()不仅加载模块,而且引用模块。

1
2
3
4
5
6
7
kissy.add('base,node',function(S,Base,Node){
},{
ATTRS:{}
}
return
)

注意区别,kissy.use()还需要配置依赖项。

1
2
3
4
5
6
7
8
9
10
11
12
//引用本地模块
kissy.use('fp/mods/lu',function(S,Base,Node){
},{
ATTRS:{}
return
},{
requires: [
'../../base/base'
]
}
)