CCClass 进阶参考
相比其它 JavaScript 的类型系统,CCClass 的特别之处在于功能强大,能够灵活的定义丰富的元数据。CCClass 的技术细节比较丰富,你可以在开发过程中慢慢熟悉。本文档将列举它的详细用法,阅读前需要先掌握 使用 cc.Class 声明类型。
原型对象参数说明
cc.Class({
// 类名,用于序列化
// 值类型:String
name: "Character",
// 基类,可以是任意创建好的 cc.Class
// 值类型:Function
extends: cc.Component,
// 构造函数
// 值类型:Function
ctor: function () {},
// 属性定义(方式一,直接定义)
properties: {
text: ""
},
// 属性定义(方式二,使用 ES6 的箭头函数,详见下文)
properties: () => ({
text: ""
}),
// 实例方法
print: function () {
cc.log(this.text);
},
// 静态成员定义
// 值类型:Object
statics: {
_count: 0,
getCount: function () {}
},
// 提供给 Component 的子类专用的参数字段
// 值类型:Object
editor: {
disallowMultiple: true
}
});
成员
实例变量
var Sprite = cc.Class({
ctor: function () {
// 声明实例变量并赋默认值
this.url = "";
this.id = 0;
}
});
实例方法
var Sprite = cc.Class({
ctor: function () {
this.text = "this is sprite";
},
// 声明一个名叫 "print" 的实例方法
print: function () {
cc.log(this.text);
}
});
var obj = new Sprite();
// 调用实例方法
obj.print();
静态变量和静态方法
静态变量或静态方法可以在原型对象的 statics
中声明
var Sprite = cc.Class({
statics: {
// 声明静态变量
count: 0,
// 声明静态方法
getBounds: function (spriteList) {
// ...
}
}
});
上面的代码等价于:
var Sprite = cc.Class({ ... });
// 声明静态变量
Sprite.count = 0;
// 声明静态方法
Sprite.getBounds = function (spriteList) {
// ...
};
继承
执行顺序 : 父类的构造函数 -> 子类的构造函数
var Node = cc.Class({
ctor: function () {
this.name = "node";
}
});
var Sprite = cc.Class({
extends: Node,
ctor: function () {
// 子构造函数被调用前,父构造函数已经被调用过,所以 this.name 已经被初始化过了
cc.log(this.name); // "node"
// 重新设置 this.name
this.name = "sprite";
}
});
var obj = new Sprite();
cc.log(obj.name); // "sprite"
重写
所有成员方法都是虚方法,子类方法可以直接重写父类方法
var Shape = cc.Class({
getName: function () {
return "shape";
}
});
var Rect = cc.Class({
extends: Shape,
getName: function () {
return "rect";
}
});
var obj = new Rect();
cc.log(obj.getName()); // "rect"
调用父类方法
使用 CCClass
封装的 this._super
var Shape = cc.Class({
getName: function () {
return "shape";
}
});
var Rect = cc.Class({
extends: Shape,
getName: function () {
var baseName = this._super();
return baseName + " (rect)";
}
});
var obj = new Rect();
cc.log(obj.getName()); // "shape (rect)"
属性
- 属性是特殊的实例变量,能够显示在 属性检查器 中,也能被序列化
- 属性不用在构造函数里定义
- 在构造函数被调用前,属性已经被赋为默认值了,可以在构造函数内访问到
var Sprite = cc.Class({
ctor: function () {
this.img = LoadImage();
},
properties: {
img: {
default: null,
type: Image
}
}
});
属性参数
所有属性参数都是可选的,但至少必须声明 default, get, set 参数中的其中一个
default 参数
允许设置为以下几种值类型:
- 任意 number, string 或 boolean 类型的值
- null 或 undefined
- 继承自 cc.ValueType 的子类,如 cc.Vec2, cc.Color 或 cc.Rect 的实例化对象:
properties: {
pos: {
default: new cc.Vec2(),
}
}
- 空数组 [] 或空对象 {}
- 一个允许返回任意类型值的 function,这个 function 会在每次实例化该类时重新调用,并且以返回值作为新的默认值
properties: {
pos: {
default: function () {
return [1, 2, 3];
},
}
}
visible 参数
如果以下划线开头,则默认不显示在 属性检查器,否则默认显示 _id
隐藏,id
显示
serializable 参数
指定了 default 默认值的属性默认情况下都会被序列化,序列化后就会将编辑器中设置好的值保存到场景等资源文件中,并且在加载场景时自动还原之前设置好的值。如果不想序列化,可以设置serializable: false
temp_url: {
default: "",
serializable: false
}
type 参数
当 default 不能提供足够详细的类型信息时,为了能在 属性检查器 显示正确的输入控件,就要用 type 显式声明具体的类型:
// 节点 Node
enemy: {
default: null,
type: cc.Node
}
// 整型 Integer
score: {
default: 0,
type: cc.Integer
}
// 枚举
wrap: {
default: Texture.WrapMode.Clamp,
type: Texture.WrapMode
}
url 参数
访问 Raw Asset 资源的 url
texture: {
default: "",
url: cc.Texture2D
},
override 参数
所有属性都将被子类继承,如果子类要覆盖父类同名属性,需要显式设置 override 参数,否则会有重名警告:
_id: {
default: "",
tooltip: "my id",
override: true
},
属性延迟定义
两个类相互引用,脚本加载阶段就会出现循环引用,循环引用将导致脚本加载出错
将 properties 指定为一个 ES6 的箭头函数
// Game.js
var Game = cc.Class({
properties: () => ({
item: {
default: null,
// 引用 Item
type: require("Item")
}
})
});
module.exports = Game;
// Item.js
var Item = cc.Class({
properties: () => ({
game: {
default: null,
// 引用 Game
type: require("Game")
}
})
});
module.exports = Item;
Get 方法
get 属性本身是只读的,但返回的对象并不是只读的
var Sprite = cc.Class({
...
position: {
get: function () {
return this._position;
},
}
...
});
var obj = new Sprite();
obj.position = new cc.Vec2(10, 20); // 失败!position 是只读的!
obj.position.x = 100; // 允许!position 返回的 _position 对象本身可以修改!
Set 方法
- 如果没有和 get 一起定义,则 set 自身不能附带任何参数。
- 和 get 一样,设定了 set 以后,这个属性就不能被序列化,也不能指定默认值。
width: {
get: function () {
return this._width;
},
set: function (value) {
this._width = value;
},
type: cc.Integer,
tooltip: "The width of sprite"
}
editor 参数
editor 只能定义在 cc.Component 的子类。
cc.Class({
extends: cc.Component,
editor: {
// 允许当前组件在编辑器模式下运行。
// 默认情况下,所有组件都只会在运行时执行,也就是说它们的生命周期回调在编辑器模式下并不会触发。
//
// 值类型:Boolean
// 默认值:false
executeInEditMode: false,
// requireComponent 参数用来指定当前组件的依赖组件。
// 当组件添加到节点上时,如果依赖的组件不存在,引擎将会自动将依赖组件添加到同一个节点,防止脚本出错。
// 该选项在运行时同样有效。
//
// 值类型:Function (必须是继承自 cc.Component 的构造函数,如 cc.Sprite)
// 默认值:null
requireComponent: null,
// 脚本生命周期回调的执行优先级。
// 小于 0 的脚本将优先执行,大于 0 的脚本将最后执行。
// 该优先级只对 onLoad, onEnable, start, update 和 lateUpdate 有效,对 onDisable 和 onDestroy 无效。
//
// 值类型:Number
// 默认值:0
executionOrder: 0,
// 当本组件添加到节点上后,禁止同类型(含子类)的组件再添加到同一个节点,
// 防止逻辑发生冲突。
//
// 值类型:Boolean
// 默认值:false
disallowMultiple: false,
// menu 用来将当前组件添加到组件菜单中,方便用户查找。
//
// 值类型:String (如 "Rendering/Camera")
// 默认值:""
menu: "",
// 当设置了 "executeInEditMode" 以后,playOnFocus 可以用来设定选中当前组件所在的节点时,
// 编辑器的场景刷新频率。
// playOnFocus 如果设置为 true,场景渲染将保持 60 FPS,如果为 false,场景就只会在必要的时候进行重绘。
//
// 值类型:Boolean
// 默认值:false
playOnFocus: false,
// 自定义当前组件在 **属性检查器** 中渲染时所用的网页 url。
//
// 值类型:String
// 默认值:""
inspector: "",
// 自定义当前组件在编辑器中显示的图标 url。
//
// 值类型:String
// 默认值:""
icon: "",
// 指定当前组件的帮助文档的 url,设置过后,在 **属性检查器** 中就会出现一个帮助图标,
// 用户点击将打开指定的网页。
//
// 值类型:String
// 默认值:""
help: "",
}
});